aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--OpenSim/Addons/Groups/GroupsModule.cs273
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/RegionLoaderWebServer.cs105
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs291
-rw-r--r--OpenSim/Capabilities/Caps.cs14
-rw-r--r--OpenSim/Capabilities/CapsHandlers.cs1
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs11
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs30
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2ServerConnector.cs71
-rw-r--r--OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs9
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs332
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs16
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs227
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureRobustHandler.cs431
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs6
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs4
-rw-r--r--OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs15
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadComplete.cs3
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadRequest.cs15
-rw-r--r--OpenSim/Capabilities/LLSDAssetUploadResponse.cs33
-rw-r--r--OpenSim/Data/AssetDataBase.cs2
-rw-r--r--OpenSim/Data/IAssetData.cs2
-rw-r--r--OpenSim/Data/IProfilesData.cs2
-rw-r--r--OpenSim/Data/IUserAccountData.cs1
-rw-r--r--OpenSim/Data/MySQL/MySQLAgentPreferencesData.cs2
-rw-r--r--OpenSim/Data/MySQL/MySQLAssetData.cs97
-rw-r--r--OpenSim/Data/MySQL/MySQLFramework.cs40
-rw-r--r--OpenSim/Data/MySQL/MySQLGenericTableHandler.cs7
-rw-r--r--OpenSim/Data/MySQL/MySQLRegionData.cs73
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs320
-rw-r--r--OpenSim/Data/MySQL/MySQLUserAccountData.cs40
-rw-r--r--OpenSim/Data/MySQL/MySQLUserProfilesData.cs24
-rw-r--r--OpenSim/Data/MySQL/MySQLXAssetData.cs2
-rw-r--r--OpenSim/Data/MySQL/Resources/RegionStore.migrations24
-rw-r--r--OpenSim/Data/MySQL/Resources/UserAccount.migrations7
-rw-r--r--OpenSim/Data/Null/NullRegionData.cs20
-rw-r--r--OpenSim/Data/Null/NullSimulationData.cs5
-rw-r--r--OpenSim/Data/Null/NullUserAccountData.cs5
-rw-r--r--OpenSim/Data/PGSQL/PGSQLAssetData.cs3
-rw-r--r--OpenSim/Data/PGSQL/PGSQLSimulationData.cs5
-rw-r--r--OpenSim/Data/PGSQL/PGSQLUserAccountData.cs5
-rw-r--r--OpenSim/Data/PGSQL/Resources/UserProfiles.migrations2
-rw-r--r--OpenSim/Data/SQLite/Resources/RegionStore.migrations22
-rw-r--r--OpenSim/Data/SQLite/Resources/UserAccount.migrations8
-rw-r--r--OpenSim/Data/SQLite/Resources/UserProfiles.migrations2
-rw-r--r--OpenSim/Data/SQLite/SQLiteAssetData.cs4
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs46
-rw-r--r--OpenSim/Data/SQLite/SQLiteUserAccountData.cs5
-rw-r--r--OpenSim/Data/SQLite/SQLiteUserProfilesData.cs1
-rw-r--r--OpenSim/Framework/AgentCircuitData.cs4
-rw-r--r--OpenSim/Framework/AnimationSet.cs168
-rw-r--r--OpenSim/Framework/AssetBase.cs11
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs107
-rw-r--r--OpenSim/Framework/AvatarWearable.cs24
-rw-r--r--OpenSim/Framework/BlockingQueue.cs5
-rw-r--r--OpenSim/Framework/ChildAgentDataUpdate.cs222
-rw-r--r--OpenSim/Framework/ColliderData.cs1
-rw-r--r--OpenSim/Framework/ConfigurationMember.cs530
-rw-r--r--OpenSim/Framework/Console/CommandConsole.cs4
-rw-r--r--OpenSim/Framework/CustomTypes.cs43
-rw-r--r--OpenSim/Framework/EntityTransferContext.cs70
-rw-r--r--OpenSim/Framework/EstateSettings.cs36
-rw-r--r--OpenSim/Framework/IClientAPI.cs44
-rw-r--r--OpenSim/Framework/ILandChannel.cs2
-rw-r--r--OpenSim/Framework/ILandObject.cs2
-rw-r--r--OpenSim/Framework/IMoneyModule.cs3
-rw-r--r--OpenSim/Framework/ISceneAgent.cs9
-rw-r--r--OpenSim/Framework/LandData.cs34
-rw-r--r--OpenSim/Framework/LandUpdateArgs.cs3
-rw-r--r--OpenSim/Framework/LocklessQueue.cs8
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs21
-rw-r--r--OpenSim/Framework/Monitoring/ServerStatsCollector.cs43
-rwxr-xr-xOpenSim/Framework/Monitoring/SimExtraStatsCollector.cs28
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs13
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs4
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs6
-rw-r--r--OpenSim/Framework/NetworkServersInfo.cs2
-rw-r--r--OpenSim/Framework/OSChatMessage.cs21
-rw-r--r--OpenSim/Framework/ObjectChangeData.cs80
-rw-r--r--OpenSim/Framework/ParcelMediaCommandEnum.cs2
-rw-r--r--OpenSim/Framework/PermissionsUtil.cs4
-rw-r--r--OpenSim/Framework/PluginLoader.cs17
-rw-r--r--OpenSim/Framework/PrimitiveBaseShape.cs38
-rw-r--r--OpenSim/Framework/PriorityQueue.cs37
-rw-r--r--OpenSim/Framework/RegionInfo.cs271
-rw-r--r--OpenSim/Framework/RegionSettings.cs24
-rw-r--r--OpenSim/Framework/RestClient.cs27
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs22
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs116
-rw-r--r--OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs6
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs60
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs361
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs2
-rw-r--r--OpenSim/Framework/Servers/Tests/OSHttpTests.cs324
-rw-r--r--OpenSim/Framework/SimStats.cs14
-rw-r--r--OpenSim/Framework/TaskInventoryDictionary.cs189
-rw-r--r--OpenSim/Framework/TaskInventoryItem.cs2
-rw-r--r--OpenSim/Framework/TerrainData.cs320
-rw-r--r--OpenSim/Framework/Tests/AgentCircuitDataTest.cs3
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs11
-rw-r--r--OpenSim/Framework/ThrottleOutPacketType.cs2
-rw-r--r--OpenSim/Framework/UserProfileData.cs2
-rw-r--r--OpenSim/Framework/Util.cs246
-rw-r--r--OpenSim/Framework/WearableCacheItem.cs70
-rw-r--r--OpenSim/Framework/WebUtil.cs63
-rw-r--r--OpenSim/Region/Application/Application.cs1
-rw-r--r--OpenSim/Region/Application/OpenSim.cs30
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs71
-rw-r--r--OpenSim/Region/Application/RegionApplicationBase.cs26
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs1070
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs727
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs474
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs21
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs404
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs426
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs18
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs297
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs5
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs164
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs17
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1800
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs325
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs356
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs35
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs10
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs17
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs373
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs28
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs239
-rw-r--r--OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs194
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs14
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs399
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs78
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs235
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs87
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs8
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs67
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs247
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs109
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs181
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs178
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs104
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs1011
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs31
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs285
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs96
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs225
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs439
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs81
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs7
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs13
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs29
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs34
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs13
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs8
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs12
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs15
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs40
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs31
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs32
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs767
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs215
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs127
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs176
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs69
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs29
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs28
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs16
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs633
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs54
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs119
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs1488
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IHttpRequests.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/INPCModule.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionConsole.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRestartModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISearchModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs47
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs33
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldComm.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs101
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs382
-rw-r--r--OpenSim/Region/Framework/Scenes/CollisionSounds.cs304
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs280
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs72
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPMaterial.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPVehicle.cs792
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs440
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs160
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs6
-rwxr-xr-xOpenSim/Region/Framework/Scenes/Scene.cs1339
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs57
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SceneGraph.cs542
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs246
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2042
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs1669
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs813
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2845
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs137
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SimStatsReporter.cs629
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs1589
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs58
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs3
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs26
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs82
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs325
-rw-r--r--OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs1
-rw-r--r--OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs36
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerLargeLandChannel.cs1
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerPermissionModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/RegionCombinerModule/RegionConnections.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs7
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs7
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs67
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs78
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs4
-rw-r--r--OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs6
-rw-r--r--OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs3
-rw-r--r--OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs3
-rw-r--r--OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs2
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs69
-rw-r--r--OpenSim/Region/PhysicsModules/BulletS/BSScene.cs5
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs1
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/BSShapes.cs10
-rwxr-xr-xOpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs4
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs81
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs19
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs62
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs4
-rw-r--r--OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs25
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs4
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEModule.cs85
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs571
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs11
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/OdeScene.cs390
-rw-r--r--OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs18
-rw-r--r--OpenSim/Region/PhysicsModules/POS/POSCharacter.cs3
-rw-r--r--OpenSim/Region/PhysicsModules/POS/POSPrim.cs5
-rw-r--r--OpenSim/Region/PhysicsModules/POS/POSScene.cs2
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs29
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs283
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs66
-rw-r--r--OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs45
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs2024
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs1978
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs1096
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs933
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs97
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs3962
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs680
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs2830
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs356
-rw-r--r--OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs61
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/HelperTypes.cs340
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs633
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs1465
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs1708
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/Properties/AssemblyInfo.cs36
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMap.cs244
-rw-r--r--OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMesh.cs220
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs117
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs3950
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs170
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs32
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs32
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs46
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs20
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs71
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs17
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs91
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs21
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp48
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs45
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs77
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs51
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs2
-rw-r--r--OpenSim/Server/Base/HttpServerBase.cs33
-rw-r--r--OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs3
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs2
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs2
-rw-r--r--OpenSim/Server/Handlers/Login/LLLoginHandlers.cs11
-rw-r--r--OpenSim/Server/Handlers/Map/MapAddServerConnector.cs15
-rw-r--r--OpenSim/Server/Handlers/Map/MapGetServerConnector.cs28
-rw-r--r--OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs253
-rw-r--r--OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs1
-rw-r--r--OpenSim/Server/Handlers/Simulation/AgentHandlers.cs53
-rw-r--r--OpenSim/Server/ServerMain.cs5
-rw-r--r--OpenSim/Services/AssetService/AssetService.cs5
-rw-r--r--OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs9
-rw-r--r--OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs90
-rw-r--r--OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs11
-rw-r--r--OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs19
-rw-r--r--OpenSim/Services/Base/ServiceBase.cs2
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs366
-rw-r--r--OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs7
-rw-r--r--OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs68
-rw-r--r--OpenSim/Services/Connectors/Grid/GridServicesConnector.cs10
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs6
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs3
-rw-r--r--OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs1
-rw-r--r--OpenSim/Services/Connectors/Land/LandServicesConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs66
-rw-r--r--OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs6
-rw-r--r--OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs11
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs6
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs3
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs13
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs5
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs31
-rw-r--r--OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs5
-rw-r--r--OpenSim/Services/GridService/GridService.cs29
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs6
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs2
-rw-r--r--OpenSim/Services/HypergridService/UserAccountCache.cs5
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs4
-rw-r--r--OpenSim/Services/Interfaces/IAttachmentsService.cs38
-rw-r--r--OpenSim/Services/Interfaces/IAuthenticationService.cs1
-rw-r--r--OpenSim/Services/Interfaces/IAvatarService.cs11
-rw-r--r--OpenSim/Services/Interfaces/IGridService.cs35
-rw-r--r--OpenSim/Services/Interfaces/ILoginService.cs4
-rw-r--r--OpenSim/Services/Interfaces/IMapImageService.cs6
-rw-r--r--OpenSim/Services/Interfaces/ISimulationService.cs19
-rw-r--r--OpenSim/Services/Interfaces/IUserAccountService.cs5
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginResponse.cs22
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs32
-rw-r--r--OpenSim/Services/MapImageService/MapImageService.cs119
-rw-r--r--OpenSim/Services/SimulationService/SimulationDataService.cs5
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountService.cs21
-rw-r--r--OpenSim/Services/UserProfilesService/UserProfilesService.cs2
-rw-r--r--OpenSim/Tests/Clients/Grid/GridClient.cs205
-rw-r--r--OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs2
-rw-r--r--OpenSim/Tests/Common/Helpers/SceneHelpers.cs2
-rw-r--r--OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs3
-rw-r--r--OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs10
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs59
-rw-r--r--OpenSim/Tests/Common/Mock/TestLandChannel.cs1
-rw-r--r--OpenSim/Tests/Performance/NPCPerformanceTests.cs4
-rwxr-xr-xbin/MsgPack.dllbin0 -> 37376 bytes
-rw-r--r--bin/OpenSim.Region.PhysicsModule.ubOde.dll.config7
-rw-r--r--bin/OpenSim.ini.example25
-rw-r--r--bin/OpenSimDefaults.ini71
-rw-r--r--bin/assets/TexturesAssetSet/defaultalpha.jp2bin0 -> 319 bytes
-rw-r--r--bin/enter_uuid.xml7
-rwxr-xr-x[-rw-r--r--]bin/lib32/libode.sobin3051566 -> 3134141 bytes
-rwxr-xr-xbin/lib32/ode.dllbin496640 -> 541696 bytes
-rwxr-xr-xbin/lib64/ode.dllbin656384 -> 637952 bytes
-rw-r--r--bin/set_object_owner.xml8
-rw-r--r--prebuild.xml93
467 files changed, 50569 insertions, 14566 deletions
diff --git a/.gitignore b/.gitignore
index 94f896d..d1f7710 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
1.project 1.project
2.settings 2.settings
3.gitignore
3*.csproj 4*.csproj
4*.csproj.user 5*.csproj.user
5*.build 6*.build
@@ -10,6 +11,7 @@
10*.pidb 11*.pidb
11*.dll.build 12*.dll.build
12*.dll 13*.dll
14*.log
13 15
14# Ignore .user and .suo files as these are user preference specific 16# Ignore .user and .suo files as these are user preference specific
15# http://stackoverflow.com/questions/72298/should-i-add-the-visual-studio-suo-and-user-files-to-source-control 17# http://stackoverflow.com/questions/72298/should-i-add-the-visual-studio-suo-and-user-files-to-source-control
@@ -29,6 +31,7 @@
29*/*/*/*/*/bin 31*/*/*/*/*/bin
30*/*/*/*/*/*/bin 32*/*/*/*/*/*/bin
31*/*/*/*/*/*/*/bin 33*/*/*/*/*/*/*/bin
34addon-modules/
32bin/Debug/*.dll 35bin/Debug/*.dll
33bin/*.dll.mdb 36bin/*.dll.mdb
34bin/*.db 37bin/*.db
diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs
index d121d1a..da8c9ea 100644
--- a/OpenSim/Addons/Groups/GroupsModule.cs
+++ b/OpenSim/Addons/Groups/GroupsModule.cs
@@ -137,13 +137,6 @@ namespace OpenSim.Groups
137 137
138 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 138 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
139 139
140 scene.EventManager.OnNewClient += OnNewClient;
141 scene.EventManager.OnMakeRootAgent += OnMakeRoot;
142 scene.EventManager.OnMakeChildAgent += OnMakeChild;
143 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
144 // The InstantMessageModule itself doesn't do this,
145 // so lets see if things explode if we don't do it
146 // scene.EventManager.OnClientClosed += OnClientClosed;
147 140
148 if (m_groupData == null) 141 if (m_groupData == null)
149 { 142 {
@@ -182,6 +175,13 @@ namespace OpenSim.Groups
182 m_sceneList.Add(scene); 175 m_sceneList.Add(scene);
183 } 176 }
184 177
178 scene.EventManager.OnNewClient += OnNewClient;
179 scene.EventManager.OnMakeRootAgent += OnMakeRoot;
180 scene.EventManager.OnMakeChildAgent += OnMakeChild;
181 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
182 // The InstantMessageModule itself doesn't do this,
183 // so lets see if things explode if we don't do it
184 // scene.EventManager.OnClientClosed += OnClientClosed;
185 185
186 } 186 }
187 187
@@ -237,6 +237,7 @@ namespace OpenSim.Groups
237 client.OnRequestAvatarProperties += OnRequestAvatarProperties; 237 client.OnRequestAvatarProperties += OnRequestAvatarProperties;
238 } 238 }
239 239
240
240 private void OnMakeRoot(ScenePresence sp) 241 private void OnMakeRoot(ScenePresence sp)
241 { 242 {
242 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 243 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -245,8 +246,9 @@ namespace OpenSim.Groups
245 // Used for Notices and Group Invites/Accept/Reject 246 // Used for Notices and Group Invites/Accept/Reject
246 sp.ControllingClient.OnInstantMessage += OnInstantMessage; 247 sp.ControllingClient.OnInstantMessage += OnInstantMessage;
247 248
248 // Send client their groups information. 249 // we should send a DataUpdate here for compatibility,
249 SendAgentGroupDataUpdate(sp.ControllingClient, sp.UUID); 250 // but this is a bad place and a bad thread to do it
251 // also current viewers do ignore it and ask later on a much nicer thread
250 } 252 }
251 253
252 private void OnMakeChild(ScenePresence sp) 254 private void OnMakeChild(ScenePresence sp)
@@ -262,23 +264,28 @@ namespace OpenSim.Groups
262 { 264 {
263 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 265 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
264 266
265 //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray();
266 GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); 267 GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID);
267 remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); 268 remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups);
268 } 269 }
269 270
270 /* 271 private void OnClientClosed(UUID AgentId, Scene scene)
271 * This becomes very problematic in a shared module. In a shared module you may have more then one
272 * reference to IClientAPI's, one for 0 or 1 root connections, and 0 or more child connections.
273 * The OnClientClosed event does not provide anything to indicate which one of those should be closed
274 * nor does it provide what scene it was from so that the specific reference can be looked up.
275 * The InstantMessageModule.cs does not currently worry about unregistering the handles,
276 * and it should be an issue, since it's the client that references us not the other way around
277 * , so as long as we don't keep a reference to the client laying around, the client can still be GC'ed
278 private void OnClientClosed(UUID AgentId)
279 { 272 {
280 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 273 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
274 if (scene == null)
275 return;
281 276
277 ScenePresence sp = scene.GetScenePresence(AgentId);
278 IClientAPI client = sp.ControllingClient;
279 if (client != null)
280 {
281 client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest;
282 client.OnRequestAvatarProperties -= OnRequestAvatarProperties;
283 // make child possible not called?
284 client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest;
285 client.OnInstantMessage -= OnInstantMessage;
286 }
287
288 /*
282 lock (m_ActiveClients) 289 lock (m_ActiveClients)
283 { 290 {
284 if (m_ActiveClients.ContainsKey(AgentId)) 291 if (m_ActiveClients.ContainsKey(AgentId))
@@ -296,31 +303,20 @@ namespace OpenSim.Groups
296 if (m_debugEnabled) m_log.WarnFormat("[Groups]: Client closed that wasn't registered here."); 303 if (m_debugEnabled) m_log.WarnFormat("[Groups]: Client closed that wasn't registered here.");
297 } 304 }
298 305
299
300 }
301 } 306 }
302 */ 307 */
303 308
309 }
310
304 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) 311 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID)
305 { 312 {
306 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 313 // this a private message for own agent only
307 314 if (dataForAgentID != GetRequestingAgentID(remoteClient))
308 UUID activeGroupID = UUID.Zero; 315 return;
309 string activeGroupTitle = string.Empty;
310 string activeGroupName = string.Empty;
311 ulong activeGroupPowers = (ulong)GroupPowers.None;
312
313 GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentIDStr(remoteClient), dataForAgentID.ToString());
314 if (membership != null)
315 {
316 activeGroupID = membership.GroupID;
317 activeGroupTitle = membership.GroupTitle;
318 activeGroupPowers = membership.GroupPowers;
319 }
320
321 SendAgentDataUpdate(remoteClient, dataForAgentID, activeGroupID, activeGroupName, activeGroupPowers, activeGroupTitle);
322 316
323 SendScenePresenceUpdate(dataForAgentID, activeGroupTitle); 317 SendAgentGroupDataUpdate(remoteClient, false);
318 // its a info request not a change, so nothing is sent to others
319 // they do get the group title with the avatar object update on arrivel to a region
324 } 320 }
325 321
326 private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient) 322 private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient)
@@ -395,11 +391,12 @@ namespace OpenSim.Groups
395 391
396 OutgoingInstantMessage(msg, invitee); 392 OutgoingInstantMessage(msg, invitee);
397 393
398 UpdateAllClientsWithGroupInfo(invitee); 394 IClientAPI client = GetActiveClient(invitee);
395 if (client != null)
396 SendDataUpdate(remoteClient, true);
399 } 397 }
400 398
401 m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID); 399 m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentIDStr(remoteClient), inviteID);
402
403 } 400 }
404 401
405 // Reject 402 // Reject
@@ -462,7 +459,6 @@ namespace OpenSim.Groups
462 { 459 {
463 OnNewGroupNotice(GroupID, NoticeID); 460 OnNewGroupNotice(GroupID, NoticeID);
464 } 461 }
465
466 462
467 // Send notice out to everyone that wants notices 463 // Send notice out to everyone that wants notices
468 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID)) 464 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID))
@@ -508,7 +504,6 @@ namespace OpenSim.Groups
508 504
509 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0); 505 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
510 } 506 }
511
512 } 507 }
513 508
514 // Interop, received special 210 code for ejecting a group member 509 // Interop, received special 210 code for ejecting a group member
@@ -583,11 +578,7 @@ namespace OpenSim.Groups
583 578
584 m_groupData.SetAgentActiveGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID); 579 m_groupData.SetAgentActiveGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID);
585 580
586 // Changing active group changes title, active powers, all kinds of things 581 SendAgentGroupDataUpdate(remoteClient, true);
587 // anyone who is in any region that can see this client, should probably be
588 // updated with new group info. At a minimum, they should get ScenePresence
589 // updated with new title.
590 UpdateAllClientsWithGroupInfo(remoteClient.AgentId);
591 } 582 }
592 583
593 /// <summary> 584 /// <summary>
@@ -634,7 +625,6 @@ namespace OpenSim.Groups
634 } 625 }
635 626
636 return data; 627 return data;
637
638 } 628 }
639 629
640 public List<GroupRolesData> GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID) 630 public List<GroupRolesData> GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID)
@@ -781,7 +771,7 @@ namespace OpenSim.Groups
781 remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); 771 remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly");
782 772
783 // Update the founder with new group information. 773 // Update the founder with new group information.
784 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 774 SendAgentGroupDataUpdate(remoteClient, false);
785 } 775 }
786 else 776 else
787 remoteClient.SendCreateGroupReply(groupID, false, reason); 777 remoteClient.SendCreateGroupReply(groupID, false, reason);
@@ -834,7 +824,7 @@ namespace OpenSim.Groups
834 // the client currently has set active, then we need to do a scene presence update too 824 // the client currently has set active, then we need to do a scene presence update too
835 // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) 825 // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID)
836 826
837 UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); 827 SendDataUpdate(remoteClient, true);
838 } 828 }
839 829
840 830
@@ -875,7 +865,7 @@ namespace OpenSim.Groups
875 } 865 }
876 866
877 // TODO: This update really should send out updates for everyone in the role that just got changed. 867 // TODO: This update really should send out updates for everyone in the role that just got changed.
878 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 868 SendDataUpdate(remoteClient, true);
879 } 869 }
880 870
881 public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) 871 public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes)
@@ -901,7 +891,7 @@ namespace OpenSim.Groups
901 } 891 }
902 892
903 // TODO: This update really should send out updates for everyone in the role that just got changed. 893 // TODO: This update really should send out updates for everyone in the role that just got changed.
904 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 894 SendDataUpdate(remoteClient, true);
905 } 895 }
906 896
907 public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) 897 public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID)
@@ -969,14 +959,6 @@ namespace OpenSim.Groups
969 return msg; 959 return msg;
970 } 960 }
971 961
972 public void SendAgentGroupDataUpdate(IClientAPI remoteClient)
973 {
974 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
975
976 // Send agent information about his groups
977 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
978 }
979
980 public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) 962 public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID)
981 { 963 {
982 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 964 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -989,7 +971,7 @@ namespace OpenSim.Groups
989 remoteClient.SendJoinGroupReply(groupID, true); 971 remoteClient.SendJoinGroupReply(groupID, true);
990 972
991 // Should this send updates to everyone in the group? 973 // Should this send updates to everyone in the group?
992 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 974 SendAgentGroupDataUpdate(remoteClient, true);
993 975
994 if (reason != string.Empty) 976 if (reason != string.Empty)
995 // A warning 977 // A warning
@@ -1011,7 +993,7 @@ namespace OpenSim.Groups
1011 993
1012 // SL sends out notifcations to the group messaging session that the person has left 994 // SL sends out notifcations to the group messaging session that the person has left
1013 // Should this also update everyone who is in the group? 995 // Should this also update everyone who is in the group?
1014 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 996 SendAgentGroupDataUpdate(remoteClient, true);
1015 } 997 }
1016 998
1017 public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) 999 public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID)
@@ -1123,7 +1105,7 @@ namespace OpenSim.Groups
1123 1105
1124 // SL sends out messages to everyone in the group 1106 // SL sends out messages to everyone in the group
1125 // Who all should receive updates and what should they be updated with? 1107 // Who all should receive updates and what should they be updated with?
1126 UpdateAllClientsWithGroupInfo(ejecteeID); 1108 SendAgentGroupDataUpdate(remoteClient, false);
1127 } 1109 }
1128 1110
1129 public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID) 1111 public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID)
@@ -1215,71 +1197,6 @@ namespace OpenSim.Groups
1215 return child; 1197 return child;
1216 } 1198 }
1217 1199
1218 /// <summary>
1219 /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'.
1220 /// </summary>
1221 private void SendGroupMembershipInfoViaCaps(IClientAPI remoteClient, UUID dataForAgentID, GroupMembershipData[] data)
1222 {
1223 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1224
1225 // NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information
1226 // to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything.
1227 if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc)
1228 return;
1229
1230 OSDArray AgentData = new OSDArray(1);
1231 OSDMap AgentDataMap = new OSDMap(1);
1232 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID));
1233 AgentData.Add(AgentDataMap);
1234
1235 OSDArray GroupData = new OSDArray(data.Length);
1236 OSDArray NewGroupData = new OSDArray(data.Length);
1237
1238 foreach (GroupMembershipData membership in data)
1239 {
1240 if (GetRequestingAgentID(remoteClient) != dataForAgentID)
1241 {
1242 if (!membership.ListInProfile)
1243 {
1244 // If we're sending group info to remoteclient about another agent,
1245 // filter out groups the other agent doesn't want to share.
1246 continue;
1247 }
1248 }
1249
1250 OSDMap GroupDataMap = new OSDMap(6);
1251 OSDMap NewGroupDataMap = new OSDMap(1);
1252
1253 GroupDataMap.Add("GroupID", OSD.FromUUID(membership.GroupID));
1254 GroupDataMap.Add("GroupPowers", OSD.FromULong(membership.GroupPowers));
1255 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(membership.AcceptNotices));
1256 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(membership.GroupPicture));
1257 GroupDataMap.Add("Contribution", OSD.FromInteger(membership.Contribution));
1258 GroupDataMap.Add("GroupName", OSD.FromString(membership.GroupName));
1259 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(membership.ListInProfile));
1260
1261 GroupData.Add(GroupDataMap);
1262 NewGroupData.Add(NewGroupDataMap);
1263 }
1264
1265 OSDMap llDataStruct = new OSDMap(3);
1266 llDataStruct.Add("AgentData", AgentData);
1267 llDataStruct.Add("GroupData", GroupData);
1268 llDataStruct.Add("NewGroupData", NewGroupData);
1269
1270 if (m_debugEnabled)
1271 {
1272 m_log.InfoFormat("[Groups]: {0}", OSDParser.SerializeJsonString(llDataStruct));
1273 }
1274
1275 IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
1276
1277 if (queue != null)
1278 {
1279 queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient));
1280 }
1281 }
1282
1283 private void SendScenePresenceUpdate(UUID AgentID, string Title) 1200 private void SendScenePresenceUpdate(UUID AgentID, string Title)
1284 { 1201 {
1285 if (m_debugEnabled) m_log.DebugFormat("[Groups]: Updating scene title for {0} with title: {1}", AgentID, Title); 1202 if (m_debugEnabled) m_log.DebugFormat("[Groups]: Updating scene title for {0} with title: {1}", AgentID, Title);
@@ -1296,53 +1213,34 @@ namespace OpenSim.Groups
1296 presence.Grouptitle = Title; 1213 presence.Grouptitle = Title;
1297 1214
1298 if (! presence.IsChildAgent) 1215 if (! presence.IsChildAgent)
1299 presence.SendAvatarDataToAllClients(); 1216 presence.SendAvatarDataToAllAgents();
1300 } 1217 }
1301 } 1218 }
1302 } 1219 }
1303 } 1220 }
1304 1221
1305 /// <summary> 1222 public void SendAgentGroupDataUpdate(IClientAPI remoteClient)
1306 /// Send updates to all clients who might be interested in groups data for dataForClientID
1307 /// </summary>
1308 private void UpdateAllClientsWithGroupInfo(UUID dataForClientID)
1309 { 1223 {
1310 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 1224 SendAgentGroupDataUpdate(remoteClient, true);
1311
1312 // TODO: Probably isn't nessesary to update every client in every scene.
1313 // Need to examine client updates and do only what's nessesary.
1314 lock (m_sceneList)
1315 {
1316 foreach (Scene scene in m_sceneList)
1317 {
1318 scene.ForEachClient(delegate(IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); });
1319 }
1320 }
1321 } 1225 }
1322 1226
1323 /// <summary> 1227 /// <summary>
1324 /// Update remoteClient with group information about dataForAgentID 1228 /// Tell remoteClient about its agent groups, and optionally send title to others
1325 /// </summary> 1229 /// </summary>
1326 private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForAgentID) 1230 private void SendAgentGroupDataUpdate(IClientAPI remoteClient, bool tellOthers)
1327 { 1231 {
1328 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); 1232 if (m_debugEnabled) m_log.InfoFormat("[Groups]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name);
1329 1233
1330 // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff 1234 // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
1331 1235
1332 OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero); 1236 UUID agentID = GetRequestingAgentID(remoteClient);
1333 1237
1334 // Need to send a group membership update to the client 1238 SendDataUpdate(remoteClient, tellOthers);
1335 // UDP version doesn't seem to behave nicely. But we're going to send it out here
1336 // with an empty group membership to hopefully remove groups being displayed due
1337 // to the core Groups Stub
1338 //remoteClient.SendGroupMembership(new GroupMembershipData[0]);
1339 1239
1340 GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID); 1240 GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID);
1341 SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); 1241 remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray);
1342 1242
1343 //remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); 1243 remoteClient.RefreshGroupMembership();
1344 if (remoteClient.AgentId == dataForAgentID)
1345 remoteClient.RefreshGroupMembership();
1346 } 1244 }
1347 1245
1348 /// <summary> 1246 /// <summary>
@@ -1394,27 +1292,49 @@ namespace OpenSim.Groups
1394 return membershipArray; 1292 return membershipArray;
1395 } 1293 }
1396 1294
1397 1295 //tell remoteClient about its agent group info, and optionally send title to others
1398 private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) 1296 private void SendDataUpdate(IClientAPI remoteClient, bool tellOthers)
1399 { 1297 {
1400 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 1298 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1401 1299
1402 // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff 1300 UUID activeGroupID = UUID.Zero;
1403 string firstname = "Unknown", lastname = "Unknown"; 1301 string activeGroupTitle = string.Empty;
1404 string name = m_UserManagement.GetUserName(dataForAgentID); 1302 string activeGroupName = string.Empty;
1405 if (!string.IsNullOrEmpty(name)) 1303 ulong activeGroupPowers = (ulong)GroupPowers.None;
1304
1305 UUID agentID = GetRequestingAgentID(remoteClient);
1306 GroupMembershipData membership = m_groupData.GetAgentActiveMembership(agentID.ToString(), agentID.ToString());
1307 if (membership != null)
1406 { 1308 {
1407 string[] parts = name.Split(new char[] { ' ' }); 1309 activeGroupID = membership.GroupID;
1408 if (parts.Length >= 2) 1310 activeGroupTitle = membership.GroupTitle;
1409 { 1311 activeGroupPowers = membership.GroupPowers;
1410 firstname = parts[0]; 1312 activeGroupName = membership.GroupName;
1411 lastname = parts[1];
1412 }
1413 } 1313 }
1414 1314
1415 remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname, 1315 UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, agentID);
1316 string firstname, lastname;
1317 if (account != null)
1318 {
1319 firstname = account.FirstName;
1320 lastname = account.LastName;
1321 }
1322 else
1323 {
1324 firstname = "Unknown";
1325 lastname = "Unknown";
1326 }
1327
1328 remoteClient.SendAgentDataUpdate(agentID, activeGroupID, firstname,
1416 lastname, activeGroupPowers, activeGroupName, 1329 lastname, activeGroupPowers, activeGroupName,
1417 activeGroupTitle); 1330 activeGroupTitle);
1331
1332 if (tellOthers)
1333 SendScenePresenceUpdate(agentID, activeGroupTitle);
1334
1335 ScenePresence sp = (ScenePresence)remoteClient.SceneAgent;
1336 if (sp != null)
1337 sp.Grouptitle = activeGroupTitle;
1418 } 1338 }
1419 1339
1420 #endregion 1340 #endregion
@@ -1463,5 +1383,4 @@ namespace OpenSim.Groups
1463 } 1383 }
1464 1384
1465 } 1385 }
1466
1467} 1386}
diff --git a/OpenSim/ApplicationPlugins/LoadRegions/RegionLoaderWebServer.cs b/OpenSim/ApplicationPlugins/LoadRegions/RegionLoaderWebServer.cs
index 850f3e0..13d7a8a 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/RegionLoaderWebServer.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/RegionLoaderWebServer.cs
@@ -49,6 +49,9 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
49 49
50 public RegionInfo[] LoadRegions() 50 public RegionInfo[] LoadRegions()
51 { 51 {
52 int tries = 3;
53 int wait = 2000;
54
52 if (m_configSource == null) 55 if (m_configSource == null)
53 { 56 {
54 m_log.Error("[WEBLOADER]: Unable to load configuration source!"); 57 m_log.Error("[WEBLOADER]: Unable to load configuration source!");
@@ -56,7 +59,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
56 } 59 }
57 else 60 else
58 { 61 {
59 IConfig startupConfig = (IConfig) m_configSource.Configs["Startup"]; 62 IConfig startupConfig = (IConfig)m_configSource.Configs["Startup"];
60 string url = startupConfig.GetString("regionload_webserver_url", String.Empty).Trim(); 63 string url = startupConfig.GetString("regionload_webserver_url", String.Empty).Trim();
61 bool allowRegionless = startupConfig.GetBoolean("allow_regionless", false); 64 bool allowRegionless = startupConfig.GetBoolean("allow_regionless", false);
62 65
@@ -67,82 +70,74 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
67 } 70 }
68 else 71 else
69 { 72 {
70 RegionInfo[] regionInfos = new RegionInfo[] {}; 73 while (tries > 0)
71 int regionCount = 0;
72 HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url);
73 webRequest.Timeout = 30000; //30 Second Timeout
74 m_log.DebugFormat("[WEBLOADER]: Sending download request to {0}", url);
75
76 try
77 { 74 {
78 string xmlSource = String.Empty; 75 RegionInfo[] regionInfos = new RegionInfo[] { };
76 int regionCount = 0;
77 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
78 webRequest.Timeout = 30000; //30 Second Timeout
79 m_log.DebugFormat("[WEBLOADER]: Sending download request to {0}", url);
79 80
80 using (HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse()) 81 try
81 { 82 {
83 HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
82 m_log.Debug("[WEBLOADER]: Downloading region information..."); 84 m_log.Debug("[WEBLOADER]: Downloading region information...");
83 85 StreamReader reader = new StreamReader(webResponse.GetResponseStream());
84 using (Stream s = webResponse.GetResponseStream()) 86 string xmlSource = String.Empty;
87 string tempStr = reader.ReadLine();
88 while (tempStr != null)
85 { 89 {
86 using (StreamReader reader = new StreamReader(s)) 90 xmlSource = xmlSource + tempStr;
87 { 91 tempStr = reader.ReadLine();
88 string tempStr = reader.ReadLine();
89 while (tempStr != null)
90 {
91 xmlSource = xmlSource + tempStr;
92 tempStr = reader.ReadLine();
93 }
94 }
95 } 92 }
96 } 93 m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " +
97 94 xmlSource.Length);
98 m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " + 95 XmlDocument xmlDoc = new XmlDocument();
99 xmlSource.Length); 96 xmlDoc.LoadXml(xmlSource);
100 XmlDocument xmlDoc = new XmlDocument(); 97 if (xmlDoc.FirstChild.Name == "Nini")
101 xmlDoc.LoadXml(xmlSource);
102 if (xmlDoc.FirstChild.Name == "Nini")
103 {
104 regionCount = xmlDoc.FirstChild.ChildNodes.Count;
105
106 if (regionCount > 0)
107 { 98 {
108 regionInfos = new RegionInfo[regionCount]; 99 regionCount = xmlDoc.FirstChild.ChildNodes.Count;
109 int i; 100
110 for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++) 101 if (regionCount > 0)
111 { 102 {
112 m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml); 103 regionInfos = new RegionInfo[regionCount];
113 regionInfos[i] = 104 int i;
114 new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i],false,m_configSource); 105 for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++)
106 {
107 m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml);
108 regionInfos[i] =
109 new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i], false, m_configSource);
110 }
115 } 111 }
116 } 112 }
117 } 113 }
118 } 114 catch (WebException ex)
119 catch (WebException ex)
120 {
121 using (HttpWebResponse response = (HttpWebResponse)ex.Response)
122 { 115 {
123 if (response.StatusCode == HttpStatusCode.NotFound) 116 if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.NotFound)
124 { 117 {
125 if (!allowRegionless) 118 if (!allowRegionless)
126 throw ex; 119 throw ex;
127 } 120 }
128 else 121 else
129 {
130 throw ex; 122 throw ex;
131 }
132 } 123 }
133 }
134 124
135 if (regionCount > 0 | allowRegionless) 125 if (regionCount > 0 | allowRegionless)
136 { 126 return regionInfos;
137 return regionInfos; 127
138 } 128 m_log.Debug("[WEBLOADER]: Request yielded no regions.");
139 else 129 tries--;
140 { 130 if (tries > 0)
141 m_log.Error("[WEBLOADER]: No region configs were available."); 131 {
142 return null; 132 m_log.Debug("[WEBLOADER]: Retrying");
133 System.Threading.Thread.Sleep(wait);
134 }
143 } 135 }
136
137 m_log.Error("[WEBLOADER]: No region configs were available.");
138 return null;
144 } 139 }
145 } 140 }
146 } 141 }
147 } 142 }
148} 143} \ No newline at end of file
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 808d9e4..bae1582 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -74,6 +74,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
74 74
75 private string m_name = "RemoteAdminPlugin"; 75 private string m_name = "RemoteAdminPlugin";
76 private string m_version = "0.0"; 76 private string m_version = "0.0";
77 private string m_openSimVersion;
77 78
78 public string Version 79 public string Version
79 { 80 {
@@ -93,6 +94,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
93 94
94 public void Initialise(OpenSimBase openSim) 95 public void Initialise(OpenSimBase openSim)
95 { 96 {
97 m_openSimVersion = openSim.GetVersionText();
98
96 m_configSource = openSim.ConfigSource.Source; 99 m_configSource = openSim.ConfigSource.Source;
97 try 100 try
98 { 101 {
@@ -135,10 +138,13 @@ namespace OpenSim.ApplicationPlugins.RemoteController
135 availableMethods["admin_region_query"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRegionQueryMethod); 138 availableMethods["admin_region_query"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRegionQueryMethod);
136 availableMethods["admin_shutdown"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcShutdownMethod); 139 availableMethods["admin_shutdown"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcShutdownMethod);
137 availableMethods["admin_broadcast"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAlertMethod); 140 availableMethods["admin_broadcast"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAlertMethod);
141 availableMethods["admin_dialog"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcDialogMethod);
138 availableMethods["admin_restart"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRestartMethod); 142 availableMethods["admin_restart"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRestartMethod);
139 availableMethods["admin_load_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadHeightmapMethod); 143 availableMethods["admin_load_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadHeightmapMethod);
140 availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod); 144 availableMethods["admin_save_heightmap"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcSaveHeightmapMethod);
141 145
146 availableMethods["admin_reset_land"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcResetLand);
147
142 // Agent management 148 // Agent management
143 availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod); 149 availableMethods["admin_get_agents"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentsMethod);
144 availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod); 150 availableMethods["admin_teleport_agent"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcTeleportAgentMethod);
@@ -163,8 +169,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
163 availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList); 169 availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList);
164 availableMethods["admin_estate_reload"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcEstateReload); 170 availableMethods["admin_estate_reload"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcEstateReload);
165 171
166 // Land management 172 // Misc
167 availableMethods["admin_reset_land"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcResetLand); 173 availableMethods["admin_refresh_search"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshSearch);
174 availableMethods["admin_refresh_map"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshMap);
175 availableMethods["admin_get_opensim_version"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetOpenSimVersion);
176 availableMethods["admin_get_agent_count"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcGetAgentCount);
168 177
169 // Either enable full remote functionality or just selected features 178 // Either enable full remote functionality or just selected features
170 string enabledMethods = m_config.GetString("enabled_methods", "all"); 179 string enabledMethods = m_config.GetString("enabled_methods", "all");
@@ -265,25 +274,105 @@ namespace OpenSim.ApplicationPlugins.RemoteController
265 274
266 try 275 try
267 { 276 {
268 m_log.Info("[RADMIN]: Request to restart Region."); 277 Scene rebootedScene = null;
278 bool restartAll = false;
269 279
270 CheckRegionParams(requestData, responseData); 280 IConfig startupConfig = m_configSource.Configs["Startup"];
281 if (startupConfig != null)
282 {
283 if (startupConfig.GetBoolean("InworldRestartShutsDown", false))
284 {
285 rebootedScene = m_application.SceneManager.CurrentOrFirstScene;
286 restartAll = true;
287 }
288 }
271 289
272 Scene rebootedScene = null; 290 if (rebootedScene == null)
273 GetSceneFromRegionParams(requestData, responseData, out rebootedScene); 291 {
292 CheckRegionParams(requestData, responseData);
293
294 GetSceneFromRegionParams(requestData, responseData, out rebootedScene);
295 }
296
297 IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>();
274 298
275 responseData["success"] = false; 299 responseData["success"] = false;
276 responseData["accepted"] = true; 300 responseData["accepted"] = true;
277 responseData["rebooting"] = true; 301 responseData["rebooting"] = true;
278 302
279 IRestartModule restartModule = rebootedScene.RequestModuleInterface<IRestartModule>(); 303 string message;
280 if (restartModule != null) 304 List<int> times = new List<int>();
305
306 if (requestData.ContainsKey("alerts"))
281 { 307 {
282 List<int> times = new List<int> { 30, 15 }; 308 string[] alertTimes = requestData["alerts"].ToString().Split( new char[] {','});
309 if (alertTimes.Length == 1 && Convert.ToInt32(alertTimes[0]) == -1)
310 {
311 m_log.Info("[RADMIN]: Request to cancel restart.");
283 312
284 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); 313 if (restartModule != null)
285 responseData["success"] = true; 314 {
315 message = "Restart has been cancelled";
316
317 if (requestData.ContainsKey("message"))
318 message = requestData["message"].ToString();
319
320 restartModule.AbortRestart(message);
321
322 responseData["success"] = true;
323 responseData["rebooting"] = false;
324
325 return;
326 }
327 }
328 foreach (string a in alertTimes)
329 times.Add(Convert.ToInt32(a));
330 }
331 else
332 {
333 int timeout = 30;
334 if (requestData.ContainsKey("milliseconds"))
335 timeout = Int32.Parse(requestData["milliseconds"].ToString()) / 1000;
336 while (timeout > 0)
337 {
338 times.Add(timeout);
339 if (timeout > 300)
340 timeout -= 120;
341 else if (timeout > 30)
342 timeout -= 30;
343 else
344 timeout -= 15;
345 }
346 }
347
348 m_log.Info("[RADMIN]: Request to restart Region.");
349
350 message = "Region is restarting in {0}. Please save what you are doing and log out.";
351
352 if (requestData.ContainsKey("message"))
353 message = requestData["message"].ToString();
354
355 bool notice = true;
356 if (requestData.ContainsKey("noticetype")
357 && ((string)requestData["noticetype"] == "dialog"))
358 {
359 notice = false;
286 } 360 }
361
362 List<Scene> restartList;
363
364 if (restartAll)
365 restartList = m_application.SceneManager.Scenes;
366 else
367 restartList = new List<Scene>() { rebootedScene };
368
369 foreach (Scene s in m_application.SceneManager.Scenes)
370 {
371 restartModule = s.RequestModuleInterface<IRestartModule>();
372 if (restartModule != null)
373 restartModule.ScheduleRestart(UUID.Zero, message, times.ToArray(), notice);
374 }
375 responseData["success"] = true;
287 } 376 }
288 catch (Exception e) 377 catch (Exception e)
289 { 378 {
@@ -320,6 +409,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController
320 m_log.Info("[RADMIN]: Alert request complete"); 409 m_log.Info("[RADMIN]: Alert request complete");
321 } 410 }
322 411
412 public void XmlRpcDialogMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
413 {
414 Hashtable responseData = (Hashtable)response.Value;
415
416 m_log.Info("[RADMIN]: Dialog request started");
417
418 Hashtable requestData = (Hashtable)request.Params[0];
419
420 string message = (string)requestData["message"];
421 string fromuuid = (string)requestData["from"];
422 m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message);
423
424 responseData["accepted"] = true;
425 responseData["success"] = true;
426
427 m_application.SceneManager.ForEachScene(
428 delegate(Scene scene)
429 {
430 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
431 if (dialogModule != null)
432 dialogModule.SendNotificationToUsersInRegion(UUID.Zero, fromuuid, message);
433 });
434
435 m_log.Info("[RADMIN]: Dialog request complete");
436 }
437
323 private void XmlRpcLoadHeightmapMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 438 private void XmlRpcLoadHeightmapMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
324 { 439 {
325 m_log.Info("[RADMIN]: Load height maps request started"); 440 m_log.Info("[RADMIN]: Load height maps request started");
@@ -423,13 +538,32 @@ namespace OpenSim.ApplicationPlugins.RemoteController
423 message = "Region is going down now."; 538 message = "Region is going down now.";
424 } 539 }
425 540
426 m_application.SceneManager.ForEachScene( 541 if (requestData.ContainsKey("noticetype")
542 && ((string) requestData["noticetype"] == "dialog"))
543 {
544 m_application.SceneManager.ForEachScene(
545
427 delegate(Scene scene) 546 delegate(Scene scene)
547 {
548 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
549 if (dialogModule != null)
550 dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
551 });
552 }
553 else
554 {
555 if (!requestData.ContainsKey("noticetype")
556 || ((string)requestData["noticetype"] != "none"))
557 {
558 m_application.SceneManager.ForEachScene(
559 delegate(Scene scene)
428 { 560 {
429 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>(); 561 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
430 if (dialogModule != null) 562 if (dialogModule != null)
431 dialogModule.SendGeneralAlert(message); 563 dialogModule.SendGeneralAlert(message);
432 }); 564 });
565 }
566 }
433 567
434 // Perform shutdown 568 // Perform shutdown
435 System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing 569 System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing
@@ -1488,7 +1622,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1488 } 1622 }
1489 1623
1490 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>(); 1624 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
1491 Dictionary<string, object> archiveOptions = new Dictionary<string,object>(); 1625 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
1492 if (mergeOar) archiveOptions.Add("merge", null); 1626 if (mergeOar) archiveOptions.Add("merge", null);
1493 if (skipAssets) archiveOptions.Add("skipAssets", null); 1627 if (skipAssets) archiveOptions.Add("skipAssets", null);
1494 if (archiver != null) 1628 if (archiver != null)
@@ -1748,21 +1882,31 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1748 1882
1749 private void XmlRpcRegionQueryMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 1883 private void XmlRpcRegionQueryMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
1750 { 1884 {
1751 m_log.Info("[RADMIN]: Received Query XML Administrator Request");
1752
1753 Hashtable responseData = (Hashtable)response.Value; 1885 Hashtable responseData = (Hashtable)response.Value;
1754 Hashtable requestData = (Hashtable)request.Params[0]; 1886 Hashtable requestData = (Hashtable)request.Params[0];
1755 1887
1888 int flags = 0;
1889 string text = String.Empty;
1890 int health = 0;
1891 responseData["success"] = true;
1892
1756 CheckRegionParams(requestData, responseData); 1893 CheckRegionParams(requestData, responseData);
1757 1894
1758 Scene scene = null; 1895 Scene scene = null;
1759 GetSceneFromRegionParams(requestData, responseData, out scene); 1896 try
1760 1897 {
1761 int health = scene.GetHealth(); 1898 GetSceneFromRegionParams(requestData, responseData, out scene);
1762 responseData["health"] = health; 1899 health = scene.GetHealth(out flags, out text);
1900 }
1901 catch (Exception e)
1902 {
1903 responseData["error"] = null;
1904 }
1763 1905
1764 responseData["success"] = true; 1906 responseData["success"] = true;
1765 m_log.Info("[RADMIN]: Query XML Administrator Request complete"); 1907 responseData["health"] = health;
1908 responseData["flags"] = flags;
1909 responseData["message"] = text;
1766 } 1910 }
1767 1911
1768 private void XmlRpcConsoleCommandMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 1912 private void XmlRpcConsoleCommandMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
@@ -2071,7 +2215,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2071 { 2215 {
2072 Hashtable requestData = (Hashtable)request.Params[0]; 2216 Hashtable requestData = (Hashtable)request.Params[0];
2073 Hashtable responseData = (Hashtable)response.Value; 2217 Hashtable responseData = (Hashtable)response.Value;
2074
2075 string musicURL = string.Empty; 2218 string musicURL = string.Empty;
2076 UUID groupID = UUID.Zero; 2219 UUID groupID = UUID.Zero;
2077 uint flags = 0; 2220 uint flags = 0;
@@ -2081,41 +2224,129 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2081 set_group = UUID.TryParse(requestData["group"].ToString(), out groupID); 2224 set_group = UUID.TryParse(requestData["group"].ToString(), out groupID);
2082 if (requestData.Contains("music") && requestData["music"] != null) 2225 if (requestData.Contains("music") && requestData["music"] != null)
2083 { 2226 {
2227
2084 musicURL = requestData["music"].ToString(); 2228 musicURL = requestData["music"].ToString();
2085 set_music = true; 2229 set_music = true;
2086 } 2230 }
2231
2087 if (requestData.Contains("flags") && requestData["flags"] != null) 2232 if (requestData.Contains("flags") && requestData["flags"] != null)
2088 set_flags = UInt32.TryParse(requestData["flags"].ToString(), out flags); 2233 set_flags = UInt32.TryParse(requestData["flags"].ToString(), out flags);
2089 2234
2090 m_log.InfoFormat("[RADMIN]: Received Reset Land Request group={0} musicURL={1} flags={2}", 2235 m_log.InfoFormat("[RADMIN]: Received Reset Land Request group={0} musicURL={1} flags={2}",
2091 (set_group ? groupID.ToString() : "unchanged"), 2236 (set_group ? groupID.ToString() : "unchanged"),
2092 (set_music ? musicURL : "unchanged"), 2237 (set_music ? musicURL : "unchanged"),
2093 (set_flags ? flags.ToString() : "unchanged")); 2238 (set_flags ? flags.ToString() : "unchanged"));
2094 2239
2095 m_application.SceneManager.ForEachScene(delegate(Scene s) 2240 m_application.SceneManager.ForEachScene(delegate (Scene s)
2096 { 2241 {
2097 List<ILandObject> parcels = s.LandChannel.AllParcels(); 2242 List<ILandObject> parcels = s.LandChannel.AllParcels();
2098 foreach (ILandObject p in parcels) 2243 foreach (ILandObject p in parcels)
2099 { 2244 {
2100 if (set_music) 2245 if (set_music)
2101 p.LandData.MusicURL = musicURL; 2246 p.LandData.MusicURL = musicURL;
2102
2103 if (set_group) 2247 if (set_group)
2104 p.LandData.GroupID = groupID; 2248 p.LandData.GroupID = groupID;
2105
2106 if (set_flags) 2249 if (set_flags)
2107 p.LandData.Flags = flags; 2250 p.LandData.Flags = flags;
2108
2109 s.LandChannel.UpdateLandObject(p.LandData.LocalID, p.LandData); 2251 s.LandChannel.UpdateLandObject(p.LandData.LocalID, p.LandData);
2110 } 2252 }
2111 } 2253 }
2112 ); 2254 );
2255 responseData["success"] = true;
2256 m_log.Info("[RADMIN]: Reset Land Request complete");
2257 }
2258
2259 private void XmlRpcRefreshSearch(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
2260 {
2261 m_log.Info("[RADMIN]: Received Refresh Search Request");
2262
2263 Hashtable responseData = (Hashtable)response.Value;
2264 Hashtable requestData = (Hashtable)request.Params[0];
2265
2266 CheckRegionParams(requestData, responseData);
2267
2268 Scene scene = null;
2269 GetSceneFromRegionParams(requestData, responseData, out scene);
2270
2271 ISearchModule searchModule = scene.RequestModuleInterface<ISearchModule>();
2272 if (searchModule != null)
2273 {
2274 searchModule.Refresh();
2275 responseData["success"] = true;
2276 }
2277 else
2278 {
2279 responseData["success"] = false;
2280 }
2281
2282 m_log.Info("[RADMIN]: Refresh Search Request complete");
2283 }
2284
2285 private void XmlRpcRefreshMap(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
2286 {
2287 m_log.Info("[RADMIN]: Received Refresh Map Request");
2288
2289 Hashtable responseData = (Hashtable)response.Value;
2290 Hashtable requestData = (Hashtable)request.Params[0];
2291
2292 CheckRegionParams(requestData, responseData);
2293
2294 Scene scene = null;
2295 GetSceneFromRegionParams(requestData, responseData, out scene);
2296
2297 IMapImageUploadModule mapTileModule = scene.RequestModuleInterface<IMapImageUploadModule>();
2298 if (mapTileModule != null)
2299 {
2300 Util.FireAndForget((x) =>
2301 {
2302 mapTileModule.UploadMapTile(scene);
2303 });
2304 responseData["success"] = true;
2305 }
2306 else
2307 {
2308 responseData["success"] = false;
2309 }
2310
2311 m_log.Info("[RADMIN]: Refresh Map Request complete");
2312 }
2313
2314 private void XmlRpcGetOpenSimVersion(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
2315 {
2316 m_log.Info("[RADMIN]: Received Get OpenSim Version Request");
2317
2318 Hashtable responseData = (Hashtable)response.Value;
2113 2319
2320 responseData["version"] = m_openSimVersion;
2114 responseData["success"] = true; 2321 responseData["success"] = true;
2115 2322
2116 m_log.Info("[RADMIN]: Reset Land Request complete"); 2323 m_log.Info("[RADMIN]: Get OpenSim Version Request complete");
2117 } 2324 }
2118 2325
2326 private void XmlRpcGetAgentCount(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
2327 {
2328 m_log.Info("[RADMIN]: Received Get Agent Count Request");
2329
2330 Hashtable responseData = (Hashtable)response.Value;
2331 Hashtable requestData = (Hashtable)request.Params[0];
2332
2333 CheckRegionParams(requestData, responseData);
2334
2335 Scene scene = null;
2336 GetSceneFromRegionParams(requestData, responseData, out scene);
2337
2338 if (scene == null)
2339 {
2340 responseData["success"] = false;
2341 }
2342 else
2343 {
2344 responseData["count"] = scene.GetRootAgentCount();
2345 responseData["success"] = true;
2346 }
2347
2348 m_log.Info("[RADMIN]: Get Agent Count Request complete");
2349 }
2119 2350
2120 /// <summary> 2351 /// <summary>
2121 /// Parse a float with the given parameter name from a request data hash table. 2352 /// Parse a float with the given parameter name from a request data hash table.
@@ -2822,7 +3053,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2822 /// </summary> 3053 /// </summary>
2823 private void ApplyNextOwnerPermissions(InventoryItemBase item) 3054 private void ApplyNextOwnerPermissions(InventoryItemBase item)
2824 { 3055 {
2825 if (item.InvType == (int)InventoryType.Object) 3056 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
2826 { 3057 {
2827 uint perms = item.CurrentPermissions; 3058 uint perms = item.CurrentPermissions;
2828 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref perms); 3059 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref perms);
diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs
index 049afab..3efab8e 100644
--- a/OpenSim/Capabilities/Caps.cs
+++ b/OpenSim/Capabilities/Caps.cs
@@ -30,6 +30,7 @@ using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection; 32using System.Reflection;
33using System.Threading;
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -71,6 +72,7 @@ namespace OpenSim.Framework.Capabilities
71 private IHttpServer m_httpListener; 72 private IHttpServer m_httpListener;
72 private UUID m_agentID; 73 private UUID m_agentID;
73 private string m_regionName; 74 private string m_regionName;
75 private ManualResetEvent m_capsActive = new ManualResetEvent(false);
74 76
75 public UUID AgentID 77 public UUID AgentID
76 { 78 {
@@ -136,6 +138,7 @@ namespace OpenSim.Framework.Capabilities
136 m_agentID = agent; 138 m_agentID = agent;
137 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL); 139 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL);
138 m_regionName = regionName; 140 m_regionName = regionName;
141 m_capsActive.Reset();
139 } 142 }
140 143
141 /// <summary> 144 /// <summary>
@@ -255,5 +258,16 @@ namespace OpenSim.Framework.Capabilities
255 258
256 return caps; 259 return caps;
257 } 260 }
261
262 public void Activate()
263 {
264 m_capsActive.Set();
265 }
266
267 public bool WaitForActivation()
268 {
269 // Wait for 30s. If that elapses, return false and run without caps
270 return m_capsActive.WaitOne(120000);
271 }
258 } 272 }
259} \ No newline at end of file 273} \ No newline at end of file
diff --git a/OpenSim/Capabilities/CapsHandlers.cs b/OpenSim/Capabilities/CapsHandlers.cs
index 890df90..04cede1 100644
--- a/OpenSim/Capabilities/CapsHandlers.cs
+++ b/OpenSim/Capabilities/CapsHandlers.cs
@@ -90,6 +90,7 @@ namespace OpenSim.Framework.Capabilities
90 lock (m_capsHandlers) 90 lock (m_capsHandlers)
91 { 91 {
92 m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path); 92 m_httpListener.RemoveStreamHandler("POST", m_capsHandlers[capsName].Path);
93 m_httpListener.RemoveStreamHandler("PUT", m_capsHandlers[capsName].Path);
93 m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path); 94 m_httpListener.RemoveStreamHandler("GET", m_capsHandlers[capsName].Path);
94 m_capsHandlers.Remove(capsName); 95 m_capsHandlers.Remove(capsName);
95 } 96 }
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
index 7197049..4da6c3d 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs
@@ -416,7 +416,7 @@ namespace OpenSim.Capabilities.Handlers
416 416
417 version = containingFolder.Version; 417 version = containingFolder.Version;
418 418
419 if (fetchItems) 419 if (fetchItems && containingFolder.Type != (short)FolderType.Trash)
420 { 420 {
421 List<InventoryItemBase> itemsToReturn = contents.Items; 421 List<InventoryItemBase> itemsToReturn = contents.Items;
422 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn); 422 List<InventoryItemBase> originalItems = new List<InventoryItemBase>(itemsToReturn);
@@ -441,6 +441,10 @@ namespace OpenSim.Capabilities.Handlers
441 } 441 }
442 442
443 // Now scan for folder links and insert the items they target and those links at the head of the return data 443 // Now scan for folder links and insert the items they target and those links at the head of the return data
444
445/* dont send contents of LinkFolders.
446from docs seems this was never a spec
447
444 foreach (InventoryItemBase item in originalItems) 448 foreach (InventoryItemBase item in originalItems)
445 { 449 {
446 if (item.AssetType == (int)AssetType.LinkFolder) 450 if (item.AssetType == (int)AssetType.LinkFolder)
@@ -471,6 +475,7 @@ namespace OpenSim.Capabilities.Handlers
471 } 475 }
472 } 476 }
473 } 477 }
478*/
474 } 479 }
475 480
476// foreach (InventoryItemBase item in contents.Items) 481// foreach (InventoryItemBase item in contents.Items)
@@ -723,8 +728,8 @@ namespace OpenSim.Capabilities.Handlers
723 if (item.AssetType == (int)AssetType.Link) 728 if (item.AssetType == (int)AssetType.Link)
724 itemIDs.Add(item.AssetID); 729 itemIDs.Add(item.AssetID);
725 730
726 else if (item.AssetType == (int)AssetType.LinkFolder) 731// else if (item.AssetType == (int)AssetType.LinkFolder)
727 folderIDs.Add(item.AssetID); 732// folderIDs.Add(item.AssetID);
728 } 733 }
729 734
730 //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count); 735 //m_log.DebugFormat("[XXX]: folder {0} has {1} links and {2} linkfolders", contents.FolderID, itemIDs.Count, folderIDs.Count);
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
index c904392..1753f60 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs
@@ -64,21 +64,36 @@ namespace OpenSim.Capabilities.Handlers
64 64
65 UUID[] itemIDs = new UUID[itemsRequested.Count]; 65 UUID[] itemIDs = new UUID[itemsRequested.Count];
66 int i = 0; 66 int i = 0;
67
67 foreach (OSDMap osdItemId in itemsRequested) 68 foreach (OSDMap osdItemId in itemsRequested)
68 { 69 {
69 itemIDs[i++] = osdItemId["item_id"].AsUUID(); 70 itemIDs[i++] = osdItemId["item_id"].AsUUID();
70 } 71 }
71 72
72 InventoryItemBase[] items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs); 73 InventoryItemBase[] items = null;
73 74
74 if (items == null) 75 if (m_agentID != UUID.Zero)
76 {
77 items = m_inventoryService.GetMultipleItems(m_agentID, itemIDs);
78
79 if (items == null)
80 {
81 // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
82 m_log.WarnFormat("[FETCH INVENTORY HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
83 items = new InventoryItemBase[itemsRequested.Count];
84 InventoryItemBase item = new InventoryItemBase();
85 item.Owner = m_agentID;
86 foreach (UUID id in itemIDs)
87 {
88 item.ID = id;
89 items[i++] = m_inventoryService.GetItem(item);
90 }
91 }
92 }
93 else
75 { 94 {
76 // OMG!!! One by one!!! This is fallback code, in case the backend isn't updated
77 m_log.WarnFormat("[FETCH INVENTORY HANDLER]: GetMultipleItems failed. Falling back to fetching inventory items one by one.");
78 items = new InventoryItemBase[itemsRequested.Count]; 95 items = new InventoryItemBase[itemsRequested.Count];
79 i = 0;
80 InventoryItemBase item = new InventoryItemBase(); 96 InventoryItemBase item = new InventoryItemBase();
81 item.Owner = m_agentID;
82 foreach (UUID id in itemIDs) 97 foreach (UUID id in itemIDs)
83 { 98 {
84 item.ID = id; 99 item.ID = id;
@@ -93,7 +108,6 @@ namespace OpenSim.Capabilities.Handlers
93 // We don't know the agent that this request belongs to so we'll use the agent id of the item 108 // We don't know the agent that this request belongs to so we'll use the agent id of the item
94 // which will be the same for all items. 109 // which will be the same for all items.
95 llsdReply.agent_id = item.Owner; 110 llsdReply.agent_id = item.Owner;
96
97 llsdReply.items.Array.Add(ConvertInventoryItem(item)); 111 llsdReply.items.Array.Add(ConvertInventoryItem(item));
98 } 112 }
99 } 113 }
@@ -114,7 +128,7 @@ namespace OpenSim.Capabilities.Handlers
114 llsdItem.asset_id = invItem.AssetID; 128 llsdItem.asset_id = invItem.AssetID;
115 llsdItem.created_at = invItem.CreationDate; 129 llsdItem.created_at = invItem.CreationDate;
116 llsdItem.desc = invItem.Description; 130 llsdItem.desc = invItem.Description;
117 llsdItem.flags = (int)invItem.Flags; 131 llsdItem.flags = ((int)invItem.Flags) & 0xff;
118 llsdItem.item_id = invItem.ID; 132 llsdItem.item_id = invItem.ID;
119 llsdItem.name = invItem.Name; 133 llsdItem.name = invItem.Name;
120 llsdItem.parent_id = invItem.Folder; 134 llsdItem.parent_id = invItem.Folder;
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2ServerConnector.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2ServerConnector.cs
new file mode 100644
index 0000000..618f075
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2ServerConnector.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 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 FetchInventory2ServerConnector : ServiceConnector
39 {
40 private IInventoryService m_InventoryService;
41 private string m_ConfigName = "CapsService";
42
43 public FetchInventory2ServerConnector(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 invService = serverConfig.GetString("InventoryService", String.Empty);
54
55 if (invService == String.Empty)
56 throw new Exception("No InventoryService in config file");
57
58 Object[] args = new Object[] { config };
59 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args);
60
61 if (m_InventoryService == null)
62 throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName));
63
64 FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService, UUID.Zero);
65 IRequestHandler reqHandler
66 = new RestStreamHandler(
67 "POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest, "FetchInventory", null);
68 server.AddStreamHandler(reqHandler);
69 }
70 }
71}
diff --git a/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs
index 589602d..f7f9da9 100644
--- a/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetDisplayNames/GetDisplayNamesHandler.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Capabilities.Handlers
65 65
66 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
67 { 67 {
68 m_log.DebugFormat("[GET_DISPLAY_NAMES]: called {0}", httpRequest.Url.Query); 68// m_log.DebugFormat("[GET_DISPLAY_NAMES]: called {0}", httpRequest.Url.Query);
69 69
70 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); 70 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
71 string[] ids = query.GetValues("ids"); 71 string[] ids = query.GetValues("ids");
@@ -92,8 +92,11 @@ namespace OpenSim.Capabilities.Handlers
92 { 92 {
93 string[] parts = name.Split(new char[] {' '}); 93 string[] parts = name.Split(new char[] {' '});
94 OSDMap osdname = new OSDMap(); 94 OSDMap osdname = new OSDMap();
95 osdname["display_name_next_update"] = OSD.FromDate(DateTime.MinValue); 95 // a date that is valid
96 osdname["display_name_expires"] = OSD.FromDate(DateTime.Now.AddMonths(1)); 96// osdname["display_name_next_update"] = OSD.FromDate(new DateTime(1970,1,1));
97 // but send one that blocks edition, since we actually don't suport this
98 osdname["display_name_next_update"] = OSD.FromDate(DateTime.UtcNow.AddDays(8));
99 osdname["display_name_expires"] = OSD.FromDate(DateTime.UtcNow.AddMonths(1));
97 osdname["display_name"] = OSD.FromString(name); 100 osdname["display_name"] = OSD.FromString(name);
98 osdname["legacy_first_name"] = parts[0]; 101 osdname["legacy_first_name"] = parts[0];
99 osdname["legacy_last_name"] = parts[1]; 102 osdname["legacy_last_name"] = parts[1];
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index 6b67da1..a9b81f3 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -25,224 +25,242 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
28using log4net; 34using log4net;
35using Nini.Config;
29using OpenMetaverse; 36using OpenMetaverse;
30using OpenMetaverse.Imaging; 37using OpenMetaverse.StructuredData;
31using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
32using OpenSim.Framework.Servers.HttpServer; 40using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
34using System; 42using Caps = OpenSim.Framework.Capabilities.Caps;
35using System.Collections.Specialized; 43
36using System.Drawing; 44
37using System.Drawing.Imaging; 45
38using System.IO;
39using System.Reflection;
40using System.Web;
41 46
42namespace OpenSim.Capabilities.Handlers 47namespace OpenSim.Capabilities.Handlers
43{ 48{
44 public class GetMeshHandler : BaseStreamHandler 49 public class GetMeshHandler
45 { 50 {
46 private static readonly ILog m_log = 51 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
48 private IAssetService m_assetService; 54 private IAssetService m_assetService;
49 55
50 // TODO: Change this to a config option 56 public const string DefaultFormat = "vnd.ll.mesh";
51 private string m_RedirectURL = null;
52 57
53 public GetMeshHandler(string path, IAssetService assService, string name, string description, string redirectURL) 58 public GetMeshHandler(IAssetService assService)
54 : base("GET", path, name, description)
55 { 59 {
56 m_assetService = assService; 60 m_assetService = assService;
57 m_RedirectURL = redirectURL;
58 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
59 m_RedirectURL += "/";
60 } 61 }
61 62 public Hashtable Handle(Hashtable request)
62 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
63 { 63 {
64 // Try to parse the texture ID from the request URL 64 Hashtable ret = new Hashtable();
65 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); 65 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
66 string textureStr = query.GetOne("mesh_id"); 66 ret["content_type"] = "text/plain";
67 ret["keepalive"] = false;
68 ret["reusecontext"] = false;
69 ret["int_bytes"] = 0;
70 ret["int_lod"] = 0;
71 string MeshStr = (string)request["mesh_id"];
72
73
74 //m_log.DebugFormat("[GETMESH]: called {0}", MeshStr);
67 75
68 if (m_assetService == null) 76 if (m_assetService == null)
69 { 77 {
70 m_log.Error("[GETMESH]: Cannot fetch mesh " + textureStr + " without an asset service"); 78 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service");
71 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
72 } 79 }
73 80
74 UUID meshID; 81 UUID meshID;
75 if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out meshID)) 82 if (!String.IsNullOrEmpty(MeshStr) && UUID.TryParse(MeshStr, out meshID))
76 { 83 {
77 // OK, we have an array with preferred formats, possibly with only one entry 84 // m_log.DebugFormat("[GETMESH]: Received request for mesh id {0}", meshID);
78
79 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
80 AssetBase mesh;
81
82 if (!String.IsNullOrEmpty(m_RedirectURL))
83 {
84 // Only try to fetch locally cached meshes. Misses are redirected
85 mesh = m_assetService.GetCached(meshID.ToString());
86 85
87 if (mesh != null)
88 {
89 if (mesh.Type != (sbyte)AssetType.Mesh)
90 {
91 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
92 }
93 WriteMeshData(httpRequest, httpResponse, mesh);
94 }
95 else
96 {
97 string textureUrl = m_RedirectURL + "?mesh_id="+ meshID.ToString();
98 m_log.Debug("[GETMESH]: Redirecting mesh request to " + textureUrl);
99 httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
100 httpResponse.RedirectLocation = textureUrl;
101 return null;
102 }
103 }
104 else // no redirect
105 {
106 // try the cache
107 mesh = m_assetService.GetCached(meshID.ToString());
108 86
109 if (mesh == null) 87 ret = ProcessGetMesh(request, UUID.Zero, null);
110 {
111 // Fetch locally or remotely. Misses return a 404
112 mesh = m_assetService.Get(meshID.ToString());
113 88
114 if (mesh != null)
115 {
116 if (mesh.Type != (sbyte)AssetType.Mesh)
117 {
118 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
119 return null;
120 }
121 WriteMeshData(httpRequest, httpResponse, mesh);
122 return null;
123 }
124 }
125 else // it was on the cache
126 {
127 if (mesh.Type != (sbyte)AssetType.Mesh)
128 {
129 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
130 return null;
131 }
132 WriteMeshData(httpRequest, httpResponse, mesh);
133 return null;
134 }
135 }
136 89
137 // not found
138 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
139 return null;
140 } 90 }
141 else 91 else
142 { 92 {
143 m_log.Warn("[GETTEXTURE]: Failed to parse a mesh_id from GetMesh request: " + httpRequest.Url); 93 m_log.Warn("[GETMESH]: Failed to parse a mesh_id from GetMesh request: " + (string)request["uri"]);
144 } 94 }
145 95
146 return null;
147 }
148 96
149 private void WriteMeshData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture) 97 return ret;
98 }
99 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
150 { 100 {
151 string range = request.Headers.GetOne("Range"); 101 Hashtable responsedata = new Hashtable();
102 responsedata["int_response_code"] = 400; //501; //410; //404;
103 responsedata["content_type"] = "text/plain";
104 responsedata["keepalive"] = false;
105 responsedata["str_response_string"] = "Request wasn't what was expected";
106 responsedata["reusecontext"] = false;
107 responsedata["int_lod"] = 0;
108 responsedata["int_bytes"] = 0;
109
110 string meshStr = string.Empty;
152 111
153 if (!String.IsNullOrEmpty(range)) 112 if (request.ContainsKey("mesh_id"))
113 meshStr = request["mesh_id"].ToString();
114
115 UUID meshID = UUID.Zero;
116 if (!String.IsNullOrEmpty(meshStr) && UUID.TryParse(meshStr, out meshID))
154 { 117 {
155 // Range request 118 if (m_assetService == null)
156 int start, end;
157 if (TryParseRange(range, out start, out end))
158 { 119 {
159 // Before clamping start make sure we can satisfy it in order to avoid 120 responsedata["int_response_code"] = 404; //501; //410; //404;
160 // sending back the last byte instead of an error status 121 responsedata["content_type"] = "text/plain";
161 if (start >= texture.Data.Length) 122 responsedata["keepalive"] = false;
162 { 123 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
163 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; 124 responsedata["reusecontext"] = false;
164 response.ContentType = texture.Metadata.ContentType; 125 return responsedata;
165 } 126 }
166 else 127
128 AssetBase mesh = m_assetService.Get(meshID.ToString());
129
130 if (mesh != null)
131 {
132 if (mesh.Type == (SByte)AssetType.Mesh)
167 { 133 {
168 // Handle the case where no second range value was given. This is equivalent to requesting
169 // the rest of the entity.
170 if (end == -1)
171 end = int.MaxValue;
172 134
173 end = Utils.Clamp(end, 0, texture.Data.Length - 1); 135 Hashtable headers = new Hashtable();
174 start = Utils.Clamp(start, 0, end); 136 responsedata["headers"] = headers;
175 int len = end - start + 1; 137
138 string range = String.Empty;
139
140 if (((Hashtable)request["headers"])["range"] != null)
141 range = (string)((Hashtable)request["headers"])["range"];
176 142
177 if (0 == start && len == texture.Data.Length) 143 else if (((Hashtable)request["headers"])["Range"] != null)
144 range = (string)((Hashtable)request["headers"])["Range"];
145
146 if (!String.IsNullOrEmpty(range)) // Mesh Asset LOD // Physics
178 { 147 {
179 response.StatusCode = (int)System.Net.HttpStatusCode.OK; 148 // Range request
149 int start, end;
150 if (TryParseRange(range, out start, out end))
151 {
152 // Before clamping start make sure we can satisfy it in order to avoid
153 // sending back the last byte instead of an error status
154 if (start >= mesh.Data.Length)
155 {
156 responsedata["int_response_code"] = 404; //501; //410; //404;
157 responsedata["content_type"] = "text/plain";
158 responsedata["keepalive"] = false;
159 responsedata["str_response_string"] = "This range doesnt exist.";
160 responsedata["reusecontext"] = false;
161 responsedata["int_lod"] = 3;
162 return responsedata;
163 }
164 else
165 {
166 end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
167 start = Utils.Clamp(start, 0, end);
168 int len = end - start + 1;
169
170 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
171
172 if (start > 20000)
173 {
174 responsedata["int_lod"] = 3;
175 }
176 else if (start < 4097)
177 {
178 responsedata["int_lod"] = 1;
179 }
180 else
181 {
182 responsedata["int_lod"] = 2;
183 }
184
185
186 if (start == 0 && len == mesh.Data.Length) // well redudante maybe
187 {
188 responsedata["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
189 responsedata["bin_response_data"] = mesh.Data;
190 responsedata["int_bytes"] = mesh.Data.Length;
191 responsedata["reusecontext"] = false;
192 responsedata["int_lod"] = 3;
193
194 }
195 else
196 {
197 responsedata["int_response_code"] =
198 (int)System.Net.HttpStatusCode.PartialContent;
199 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end,
200 mesh.Data.Length);
201
202 byte[] d = new byte[len];
203 Array.Copy(mesh.Data, start, d, 0, len);
204 responsedata["bin_response_data"] = d;
205 responsedata["int_bytes"] = len;
206 responsedata["reusecontext"] = false;
207 }
208 }
209 }
210 else
211 {
212 m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
213 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
214 responsedata["content_type"] = "application/vnd.ll.mesh";
215 responsedata["int_response_code"] = 200;
216 responsedata["reusecontext"] = false;
217 responsedata["int_lod"] = 3;
218 }
180 } 219 }
181 else 220 else
182 { 221 {
183 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; 222 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
184 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); 223 responsedata["content_type"] = "application/vnd.ll.mesh";
224 responsedata["int_response_code"] = 200;
225 responsedata["reusecontext"] = false;
226 responsedata["int_lod"] = 3;
185 } 227 }
186 228 }
187 response.ContentLength = len; 229 // Optionally add additional mesh types here
188 response.ContentType = "application/vnd.ll.mesh"; 230 else
189 231 {
190 response.Body.Write(texture.Data, start, len); 232 responsedata["int_response_code"] = 404; //501; //410; //404;
233 responsedata["content_type"] = "text/plain";
234 responsedata["keepalive"] = false;
235 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
236 responsedata["reusecontext"] = false;
237 responsedata["int_lod"] = 1;
238 return responsedata;
191 } 239 }
192 } 240 }
193 else 241 else
194 { 242 {
195 m_log.Warn("[GETMESH]: Malformed Range header: " + range); 243 responsedata["int_response_code"] = 404; //501; //410; //404;
196 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; 244 responsedata["content_type"] = "text/plain";
245 responsedata["keepalive"] = false;
246 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
247 responsedata["reusecontext"] = false;
248 responsedata["int_lod"] = 0;
249 return responsedata;
197 } 250 }
198 } 251 }
199 else
200 {
201 // Full content request
202 response.StatusCode = (int)System.Net.HttpStatusCode.OK;
203 response.ContentLength = texture.Data.Length;
204 response.ContentType = "application/vnd.ll.mesh";
205 response.Body.Write(texture.Data, 0, texture.Data.Length);
206 }
207 }
208 252
209 /// <summary> 253 return responsedata;
210 /// Parse a range header. 254 }
211 /// </summary>
212 /// <remarks>
213 /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
214 /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
215 /// Where there is no value, -1 is returned.
216 /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
217 /// for start.</remarks>
218 /// <returns></returns>
219 /// <param name='header'></param>
220 /// <param name='start'>Start of the range. Undefined if this was not a number.</param>
221 /// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
222 private bool TryParseRange(string header, out int start, out int end) 255 private bool TryParseRange(string header, out int start, out int end)
223 { 256 {
224 start = end = 0;
225
226 if (header.StartsWith("bytes=")) 257 if (header.StartsWith("bytes="))
227 { 258 {
228 string[] rangeValues = header.Substring(6).Split('-'); 259 string[] rangeValues = header.Substring(6).Split('-');
229
230 if (rangeValues.Length == 2) 260 if (rangeValues.Length == 2)
231 { 261 {
232 if (!Int32.TryParse(rangeValues[0], out start)) 262 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
233 return false;
234
235 string rawEnd = rangeValues[1];
236
237 if (rawEnd == "")
238 {
239 end = -1;
240 return true; 263 return true;
241 }
242 else if (Int32.TryParse(rawEnd, out end))
243 {
244 return true;
245 }
246 } 264 }
247 } 265 }
248 266
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
index 19de3cf..b494aa4 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshServerConnector.cs
@@ -64,13 +64,15 @@ namespace OpenSim.Capabilities.Handlers
64 64
65 string rurl = serverConfig.GetString("GetMeshRedirectURL"); 65 string rurl = serverConfig.GetString("GetMeshRedirectURL");
66 66
67 server.AddStreamHandler( 67 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService);
68 new GetTextureHandler("/CAPS/GetMesh/" /*+ UUID.Random() */, m_AssetService, "GetMesh", null, rurl)); 68 IRequestHandler reqHandler
69 69 = new RestHTTPHandler(
70 rurl = serverConfig.GetString("GetMesh2RedirectURL"); 70 "GET",
71 71 "/CAPS/" + UUID.Random(),
72 server.AddStreamHandler( 72 httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null),
73 new GetTextureHandler("/CAPS/GetMesh2/" /*+ UUID.Random() */, m_AssetService, "GetMesh2", null, rurl)); 73 "GetMesh",
74 null);
75 server.AddStreamHandler(reqHandler); ;
74 } 76 }
75 } 77 }
76} \ No newline at end of file 78} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index 828e943..59d8b9a 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -47,10 +47,11 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
47 47
48namespace OpenSim.Capabilities.Handlers 48namespace OpenSim.Capabilities.Handlers
49{ 49{
50 public class GetTextureHandler : BaseStreamHandler 50 public class GetTextureHandler
51 { 51 {
52 private static readonly ILog m_log = 52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
54 private IAssetService m_assetService; 55 private IAssetService m_assetService;
55 56
56 public const string DefaultFormat = "x-j2c"; 57 public const string DefaultFormat = "x-j2c";
@@ -58,28 +59,28 @@ namespace OpenSim.Capabilities.Handlers
58 // TODO: Change this to a config option 59 // TODO: Change this to a config option
59 private string m_RedirectURL = null; 60 private string m_RedirectURL = null;
60 61
61 public GetTextureHandler(string path, IAssetService assService, string name, string description, string redirectURL) 62
62 : base("GET", path, name, description) 63 public GetTextureHandler(IAssetService assService)
63 { 64 {
64 m_assetService = assService; 65 m_assetService = assService;
65 m_RedirectURL = redirectURL;
66 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
67 m_RedirectURL += "/";
68 } 66 }
69 67
70 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 68 public Hashtable Handle(Hashtable request)
71 { 69 {
72 // Try to parse the texture ID from the request URL 70 Hashtable ret = new Hashtable();
73 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); 71 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
74 string textureStr = query.GetOne("texture_id"); 72 ret["content_type"] = "text/plain";
75 string format = query.GetOne("format"); 73 ret["keepalive"] = false;
74 ret["reusecontext"] = false;
75 ret["int_bytes"] = 0;
76 string textureStr = (string)request["texture_id"];
77 string format = (string)request["format"];
76 78
77 //m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr); 79 //m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr);
78 80
79 if (m_assetService == null) 81 if (m_assetService == null)
80 { 82 {
81 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); 83 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
82 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
83 } 84 }
84 85
85 UUID textureID; 86 UUID textureID;
@@ -94,30 +95,41 @@ namespace OpenSim.Capabilities.Handlers
94 } 95 }
95 else 96 else
96 { 97 {
97 formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept")); 98 formats = new string[1] { DefaultFormat }; // default
99 if (((Hashtable)request["headers"])["Accept"] != null)
100 formats = WebUtil.GetPreferredImageTypes((string)((Hashtable)request["headers"])["Accept"]);
98 if (formats.Length == 0) 101 if (formats.Length == 0)
99 formats = new string[1] { DefaultFormat }; // default 102 formats = new string[1] { DefaultFormat }; // default
100 103
101 } 104 }
102 // OK, we have an array with preferred formats, possibly with only one entry 105 // OK, we have an array with preferred formats, possibly with only one entry
103 106 bool foundtexture = false;
104 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
105 foreach (string f in formats) 107 foreach (string f in formats)
106 { 108 {
107 if (FetchTexture(httpRequest, httpResponse, textureID, f)) 109 foundtexture = FetchTexture(request, ret, textureID, f);
110 if (foundtexture)
108 break; 111 break;
109 } 112 }
113 if (!foundtexture)
114 {
115 ret["int_response_code"] = 404;
116 ret["error_status_text"] = "not found";
117 ret["str_response_string"] = "not found";
118 ret["content_type"] = "text/plain";
119 ret["keepalive"] = false;
120 ret["reusecontext"] = false;
121 ret["int_bytes"] = 0;
122 }
110 } 123 }
111 else 124 else
112 { 125 {
113 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); 126 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + (string)request["uri"]);
114 } 127 }
115 128
116// m_log.DebugFormat( 129// m_log.DebugFormat(
117// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}", 130// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
118// textureID, httpResponse.StatusCode, httpResponse.ContentLength); 131// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
119 132 return ret;
120 return null;
121 } 133 }
122 134
123 /// <summary> 135 /// <summary>
@@ -128,7 +140,7 @@ namespace OpenSim.Capabilities.Handlers
128 /// <param name="textureID"></param> 140 /// <param name="textureID"></param>
129 /// <param name="format"></param> 141 /// <param name="format"></param>
130 /// <returns>False for "caller try another codec"; true otherwise</returns> 142 /// <returns>False for "caller try another codec"; true otherwise</returns>
131 private bool FetchTexture(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID textureID, string format) 143 private bool FetchTexture(Hashtable request, Hashtable response, UUID textureID, string format)
132 { 144 {
133// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format); 145// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
134 AssetBase texture; 146 AssetBase texture;
@@ -137,86 +149,70 @@ namespace OpenSim.Capabilities.Handlers
137 if (format != DefaultFormat) 149 if (format != DefaultFormat)
138 fullID = fullID + "-" + format; 150 fullID = fullID + "-" + format;
139 151
140 if (!String.IsNullOrEmpty(m_RedirectURL)) 152 // try the cache
153 texture = m_assetService.GetCached(fullID);
154
155 if (texture == null)
141 { 156 {
142 // Only try to fetch locally cached textures. Misses are redirected 157 //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
143 texture = m_assetService.GetCached(fullID); 158
159 // Fetch locally or remotely. Misses return a 404
160 texture = m_assetService.Get(textureID.ToString());
144 161
145 if (texture != null) 162 if (texture != null)
146 { 163 {
147 if (texture.Type != (sbyte)AssetType.Texture) 164 if (texture.Type != (sbyte)AssetType.Texture)
165 return true;
166
167 if (format == DefaultFormat)
148 { 168 {
149 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; 169 WriteTextureData(request, response, texture, format);
150 return true; 170 return true;
151 } 171 }
152 WriteTextureData(httpRequest, httpResponse, texture, format); 172 else
153 }
154 else
155 {
156 string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString();
157 m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
158 httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
159 httpResponse.RedirectLocation = textureUrl;
160 return true;
161 }
162 }
163 else // no redirect
164 {
165 // try the cache
166 texture = m_assetService.GetCached(fullID);
167
168 if (texture == null)
169 {
170// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
171
172 // Fetch locally or remotely. Misses return a 404
173 texture = m_assetService.Get(textureID.ToString());
174
175 if (texture != null)
176 { 173 {
177 if (texture.Type != (sbyte)AssetType.Texture) 174 AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
178 { 175 newTexture.Data = ConvertTextureData(texture, format);
179 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; 176 if (newTexture.Data.Length == 0)
180 return true; 177 return false; // !!! Caller try another codec, please!
181 } 178
182 if (format == DefaultFormat) 179 newTexture.Flags = AssetFlags.Collectable;
183 { 180 newTexture.Temporary = true;
184 WriteTextureData(httpRequest, httpResponse, texture, format); 181 newTexture.Local = true;
185 return true; 182 m_assetService.Store(newTexture);
186 } 183 WriteTextureData(request, response, newTexture, format);
187 else 184 return true;
188 {
189 AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
190 newTexture.Data = ConvertTextureData(texture, format);
191 if (newTexture.Data.Length == 0)
192 return false; // !!! Caller try another codec, please!
193
194 newTexture.Flags = AssetFlags.Collectable;
195 newTexture.Temporary = true;
196 newTexture.Local = true;
197 m_assetService.Store(newTexture);
198 WriteTextureData(httpRequest, httpResponse, newTexture, format);
199 return true;
200 }
201 } 185 }
202 } 186 }
203 else // it was on the cache 187 }
204 { 188 else // it was on the cache
205// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); 189 {
206 WriteTextureData(httpRequest, httpResponse, texture, format); 190 //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
207 return true; 191 WriteTextureData(request, response, texture, format);
208 } 192 return true;
209 } 193 }
210 194
195 //response = new Hashtable();
196
197
198 //WriteTextureData(request,response,null,format);
211 // not found 199 // not found
212// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); 200 //m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
213 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; 201 return false;
214 return true;
215 } 202 }
216 203
217 private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format) 204 private void WriteTextureData(Hashtable request, Hashtable response, AssetBase texture, string format)
218 { 205 {
219 string range = request.Headers.GetOne("Range"); 206 Hashtable headers = new Hashtable();
207 response["headers"] = headers;
208
209 string range = String.Empty;
210
211 if (((Hashtable)request["headers"])["range"] != null)
212 range = (string)((Hashtable)request["headers"])["range"];
213
214 else if (((Hashtable)request["headers"])["Range"] != null)
215 range = (string)((Hashtable)request["headers"])["Range"];
220 216
221 if (!String.IsNullOrEmpty(range)) // JP2's only 217 if (!String.IsNullOrEmpty(range)) // JP2's only
222 { 218 {
@@ -244,10 +240,8 @@ namespace OpenSim.Capabilities.Handlers
244 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution. 240 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
245 241
246// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; 242// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
247// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length)); 243 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
248// response.StatusCode = (int)System.Net.HttpStatusCode.OK; 244 response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
249 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
250 response.ContentType = texture.Metadata.ContentType;
251 } 245 }
252 else 246 else
253 { 247 {
@@ -262,41 +256,46 @@ namespace OpenSim.Capabilities.Handlers
262 256
263// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 257// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
264 258
265 // Always return PartialContent, even if the range covered the entire data length 259 response["content-type"] = texture.Metadata.ContentType;
266 // We were accidentally sending back 404 before in this situation 260
267 // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the 261 if (start == 0 && len == texture.Data.Length) // well redudante maybe
268 // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this. 262 {
269 // 263 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
270 // We also do not want to send back OK even if the whole range was satisfiable since this causes 264 response["bin_response_data"] = texture.Data;
271 // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality. 265 response["int_bytes"] = texture.Data.Length;
272// if (end > maxEnd) 266 }
273// response.StatusCode = (int)System.Net.HttpStatusCode.OK; 267 else
274// else 268 {
275 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; 269 response["int_response_code"] = (int)System.Net.HttpStatusCode.PartialContent;
276 270 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length);
277 response.ContentLength = len; 271
278 response.ContentType = texture.Metadata.ContentType; 272 byte[] d = new byte[len];
279 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length)); 273 Array.Copy(texture.Data, start, d, 0, len);
280 274 response["bin_response_data"] = d;
281 response.Body.Write(texture.Data, start, len); 275 response["int_bytes"] = len;
276 }
277// response.Body.Write(texture.Data, start, len);
282 } 278 }
283 } 279 }
284 else 280 else
285 { 281 {
286 m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range); 282 m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
287 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; 283 response["int_response_code"] = (int)System.Net.HttpStatusCode.BadRequest;
288 } 284 }
289 } 285 }
290 else // JP2's or other formats 286 else // JP2's or other formats
291 { 287 {
292 // Full content request 288 // Full content request
293 response.StatusCode = (int)System.Net.HttpStatusCode.OK; 289 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
294 response.ContentLength = texture.Data.Length;
295 if (format == DefaultFormat) 290 if (format == DefaultFormat)
296 response.ContentType = texture.Metadata.ContentType; 291 response["content_type"] = texture.Metadata.ContentType;
297 else 292 else
298 response.ContentType = "image/" + format; 293 response["content_type"] = "image/" + format;
299 response.Body.Write(texture.Data, 0, texture.Data.Length); 294
295 response["bin_response_data"] = texture.Data;
296 response["int_bytes"] = texture.Data.Length;
297
298// response.Body.Write(texture.Data, 0, texture.Data.Length);
300 } 299 }
301 300
302// if (response.StatusCode < 200 || response.StatusCode > 299) 301// if (response.StatusCode < 200 || response.StatusCode > 299)
@@ -428,4 +427,4 @@ namespace OpenSim.Capabilities.Handlers
428 return null; 427 return null;
429 } 428 }
430 } 429 }
431} \ No newline at end of file 430}
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureRobustHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureRobustHandler.cs
new file mode 100644
index 0000000..f813471
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureRobustHandler.cs
@@ -0,0 +1,431 @@
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 OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using OpenMetaverse.Imaging;
41using OpenSim.Framework;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Services.Interfaces;
46using Caps = OpenSim.Framework.Capabilities.Caps;
47
48namespace OpenSim.Capabilities.Handlers
49{
50 public class GetTextureRobustHandler : BaseStreamHandler
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 private IAssetService m_assetService;
55
56 public const string DefaultFormat = "x-j2c";
57
58 // TODO: Change this to a config option
59 private string m_RedirectURL = null;
60
61 public GetTextureRobustHandler(string path, IAssetService assService, string name, string description, string redirectURL)
62 : base("GET", path, name, description)
63 {
64 m_assetService = assService;
65 m_RedirectURL = redirectURL;
66 if (m_RedirectURL != null && !m_RedirectURL.EndsWith("/"))
67 m_RedirectURL += "/";
68 }
69
70 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
71 {
72 // Try to parse the texture ID from the request URL
73 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
74 string textureStr = query.GetOne("texture_id");
75 string format = query.GetOne("format");
76
77 //m_log.DebugFormat("[GETTEXTURE]: called {0}", textureStr);
78
79 if (m_assetService == null)
80 {
81 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
82 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
83 }
84
85 UUID textureID;
86 if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
87 {
88// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID);
89
90 string[] formats;
91 if (!string.IsNullOrEmpty(format))
92 {
93 formats = new string[1] { format.ToLower() };
94 }
95 else
96 {
97 formats = WebUtil.GetPreferredImageTypes(httpRequest.Headers.Get("Accept"));
98 if (formats.Length == 0)
99 formats = new string[1] { DefaultFormat }; // default
100
101 }
102 // OK, we have an array with preferred formats, possibly with only one entry
103
104 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
105 foreach (string f in formats)
106 {
107 if (FetchTexture(httpRequest, httpResponse, textureID, f))
108 break;
109 }
110 }
111 else
112 {
113 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
114 }
115
116// m_log.DebugFormat(
117// "[GETTEXTURE]: For texture {0} sending back response {1}, data length {2}",
118// textureID, httpResponse.StatusCode, httpResponse.ContentLength);
119
120 return null;
121 }
122
123 /// <summary>
124 ///
125 /// </summary>
126 /// <param name="httpRequest"></param>
127 /// <param name="httpResponse"></param>
128 /// <param name="textureID"></param>
129 /// <param name="format"></param>
130 /// <returns>False for "caller try another codec"; true otherwise</returns>
131 private bool FetchTexture(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID textureID, string format)
132 {
133// m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
134 AssetBase texture;
135
136 string fullID = textureID.ToString();
137 if (format != DefaultFormat)
138 fullID = fullID + "-" + format;
139
140 if (!String.IsNullOrEmpty(m_RedirectURL))
141 {
142 // Only try to fetch locally cached textures. Misses are redirected
143 texture = m_assetService.GetCached(fullID);
144
145 if (texture != null)
146 {
147 if (texture.Type != (sbyte)AssetType.Texture)
148 {
149 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
150 return true;
151 }
152 WriteTextureData(httpRequest, httpResponse, texture, format);
153 }
154 else
155 {
156 string textureUrl = m_RedirectURL + "?texture_id="+ textureID.ToString();
157 m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
158 httpResponse.StatusCode = (int)OSHttpStatusCode.RedirectMovedPermanently;
159 httpResponse.RedirectLocation = textureUrl;
160 return true;
161 }
162 }
163 else // no redirect
164 {
165 // try the cache
166 texture = m_assetService.GetCached(fullID);
167
168 if (texture == null)
169 {
170// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
171
172 // Fetch locally or remotely. Misses return a 404
173 texture = m_assetService.Get(textureID.ToString());
174
175 if (texture != null)
176 {
177 if (texture.Type != (sbyte)AssetType.Texture)
178 {
179 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
180 return true;
181 }
182 if (format == DefaultFormat)
183 {
184 WriteTextureData(httpRequest, httpResponse, texture, format);
185 return true;
186 }
187 else
188 {
189 AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
190 newTexture.Data = ConvertTextureData(texture, format);
191 if (newTexture.Data.Length == 0)
192 return false; // !!! Caller try another codec, please!
193
194 newTexture.Flags = AssetFlags.Collectable;
195 newTexture.Temporary = true;
196 newTexture.Local = true;
197 m_assetService.Store(newTexture);
198 WriteTextureData(httpRequest, httpResponse, newTexture, format);
199 return true;
200 }
201 }
202 }
203 else // it was on the cache
204 {
205// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
206 WriteTextureData(httpRequest, httpResponse, texture, format);
207 return true;
208 }
209 }
210
211 // not found
212// m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
213 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
214 return true;
215 }
216
217 private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format)
218 {
219 string range = request.Headers.GetOne("Range");
220
221 if (!String.IsNullOrEmpty(range)) // JP2's only
222 {
223 // Range request
224 int start, end;
225 if (TryParseRange(range, out start, out end))
226 {
227 // Before clamping start make sure we can satisfy it in order to avoid
228 // sending back the last byte instead of an error status
229 if (start >= texture.Data.Length)
230 {
231// m_log.DebugFormat(
232// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
233// texture.ID, start, texture.Data.Length);
234
235 // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
236 // Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
237 // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
238 // received a very small texture may attempt to fetch bytes from the server past the
239 // range of data that it received originally. Whether this happens appears to depend on whether
240 // the viewer's estimation of how large a request it needs to make for certain discard levels
241 // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
242 // level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
243 // here will cause the viewer to treat the texture as bad and never display the full resolution
244 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
245
246// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
247// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
248// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
249 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
250 response.ContentType = texture.Metadata.ContentType;
251 }
252 else
253 {
254 // Handle the case where no second range value was given. This is equivalent to requesting
255 // the rest of the entity.
256 if (end == -1)
257 end = int.MaxValue;
258
259 end = Utils.Clamp(end, 0, texture.Data.Length - 1);
260 start = Utils.Clamp(start, 0, end);
261 int len = end - start + 1;
262
263// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
264
265 // Always return PartialContent, even if the range covered the entire data length
266 // We were accidentally sending back 404 before in this situation
267 // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
268 // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
269 //
270 // We also do not want to send back OK even if the whole range was satisfiable since this causes
271 // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
272// if (end > maxEnd)
273// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
274// else
275 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
276
277 response.ContentLength = len;
278 response.ContentType = texture.Metadata.ContentType;
279 response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
280
281 response.Body.Write(texture.Data, start, len);
282 }
283 }
284 else
285 {
286 m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
287 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
288 }
289 }
290 else // JP2's or other formats
291 {
292 // Full content request
293 response.StatusCode = (int)System.Net.HttpStatusCode.OK;
294 response.ContentLength = texture.Data.Length;
295 if (format == DefaultFormat)
296 response.ContentType = texture.Metadata.ContentType;
297 else
298 response.ContentType = "image/" + format;
299 response.Body.Write(texture.Data, 0, texture.Data.Length);
300 }
301
302// if (response.StatusCode < 200 || response.StatusCode > 299)
303// m_log.WarnFormat(
304// "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
305// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
306// else
307// m_log.DebugFormat(
308// "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
309// texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
310 }
311
312 /// <summary>
313 /// Parse a range header.
314 /// </summary>
315 /// <remarks>
316 /// As per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html,
317 /// this obeys range headers with two values (e.g. 533-4165) and no second value (e.g. 533-).
318 /// Where there is no value, -1 is returned.
319 /// FIXME: Need to cover the case where only a second value is specified (e.g. -4165), probably by returning -1
320 /// for start.</remarks>
321 /// <returns></returns>
322 /// <param name='header'></param>
323 /// <param name='start'>Start of the range. Undefined if this was not a number.</param>
324 /// <param name='end'>End of the range. Will be -1 if no end specified. Undefined if there was a raw string but this was not a number.</param>
325 private bool TryParseRange(string header, out int start, out int end)
326 {
327 start = end = 0;
328
329 if (header.StartsWith("bytes="))
330 {
331 string[] rangeValues = header.Substring(6).Split('-');
332
333 if (rangeValues.Length == 2)
334 {
335 if (!Int32.TryParse(rangeValues[0], out start))
336 return false;
337
338 string rawEnd = rangeValues[1];
339
340 if (rawEnd == "")
341 {
342 end = -1;
343 return true;
344 }
345 else if (Int32.TryParse(rawEnd, out end))
346 {
347 return true;
348 }
349 }
350 }
351
352 start = end = 0;
353 return false;
354 }
355
356 private byte[] ConvertTextureData(AssetBase texture, string format)
357 {
358 m_log.DebugFormat("[GETTEXTURE]: Converting texture {0} to {1}", texture.ID, format);
359 byte[] data = new byte[0];
360
361 MemoryStream imgstream = new MemoryStream();
362 Bitmap mTexture = new Bitmap(1, 1);
363 ManagedImage managedImage;
364 Image image = (Image)mTexture;
365
366 try
367 {
368 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data
369
370 imgstream = new MemoryStream();
371
372 // Decode image to System.Drawing.Image
373 if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image))
374 {
375 // Save to bitmap
376 mTexture = new Bitmap(image);
377
378 EncoderParameters myEncoderParameters = new EncoderParameters();
379 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
380
381 // Save bitmap to stream
382 ImageCodecInfo codec = GetEncoderInfo("image/" + format);
383 if (codec != null)
384 {
385 mTexture.Save(imgstream, codec, myEncoderParameters);
386 // Write the stream to a byte array for output
387 data = imgstream.ToArray();
388 }
389 else
390 m_log.WarnFormat("[GETTEXTURE]: No such codec {0}", format);
391
392 }
393 }
394 catch (Exception e)
395 {
396 m_log.WarnFormat("[GETTEXTURE]: Unable to convert texture {0} to {1}: {2}", texture.ID, format, e.Message);
397 }
398 finally
399 {
400 // Reclaim memory, these are unmanaged resources
401 // If we encountered an exception, one or more of these will be null
402 if (mTexture != null)
403 mTexture.Dispose();
404
405 if (image != null)
406 image.Dispose();
407
408 if (imgstream != null)
409 {
410 imgstream.Close();
411 imgstream.Dispose();
412 }
413 }
414
415 return data;
416 }
417
418 // From msdn
419 private static ImageCodecInfo GetEncoderInfo(String mimeType)
420 {
421 ImageCodecInfo[] encoders;
422 encoders = ImageCodecInfo.GetImageEncoders();
423 for (int j = 0; j < encoders.Length; ++j)
424 {
425 if (encoders[j].MimeType == mimeType)
426 return encoders[j];
427 }
428 return null;
429 }
430 }
431}
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
index fa0b228..479cebb 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureServerConnector.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base; 33using OpenSim.Server.Handlers.Base;
34using OpenMetaverse; 34using OpenMetaverse;
35 35
36
36namespace OpenSim.Capabilities.Handlers 37namespace OpenSim.Capabilities.Handlers
37{ 38{
38 public class GetTextureServerConnector : ServiceConnector 39 public class GetTextureServerConnector : ServiceConnector
@@ -65,7 +66,8 @@ namespace OpenSim.Capabilities.Handlers
65 string rurl = serverConfig.GetString("GetTextureRedirectURL"); 66 string rurl = serverConfig.GetString("GetTextureRedirectURL");
66 ; 67 ;
67 server.AddStreamHandler( 68 server.AddStreamHandler(
68 new GetTextureHandler("/CAPS/GetTexture/" /*+ UUID.Random() */, m_AssetService, "GetTexture", null, rurl)); 69 new GetTextureRobustHandler("/CAPS/GetTexture/", m_AssetService, "GetTexture", null, rurl));
69 } 70 }
70 } 71 }
71} \ No newline at end of file 72}
73
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
index e5d9618..61aa689 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/Tests/GetTextureHandlerTests.cs
@@ -38,6 +38,7 @@ using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Tests.Common; 39using OpenSim.Tests.Common;
40 40
41/*
41namespace OpenSim.Capabilities.Handlers.GetTexture.Tests 42namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
42{ 43{
43 [TestFixture] 44 [TestFixture]
@@ -59,4 +60,5 @@ namespace OpenSim.Capabilities.Handlers.GetTexture.Tests
59 Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound)); 60 Assert.That(resp.StatusCode, Is.EqualTo((int)System.Net.HttpStatusCode.NotFound));
60 } 61 }
61 } 62 }
62} \ No newline at end of file 63}
64*/
diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs
index 8849a59..5536564 100644
--- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Collections.Specialized; 31using System.Collections.Specialized;
31using System.Drawing; 32using System.Drawing;
32using System.Drawing.Imaging; 33using System.Drawing.Imaging;
@@ -50,6 +51,7 @@ namespace OpenSim.Capabilities.Handlers
50{ 51{
51 public class UploadBakedTextureHandler 52 public class UploadBakedTextureHandler
52 { 53 {
54
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 56
55 private Caps m_HostCapsObj; 57 private Caps m_HostCapsObj;
@@ -79,9 +81,9 @@ namespace OpenSim.Capabilities.Handlers
79 { 81 {
80 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 82 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
81 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 83 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
82 84
83 BakedTextureUploader uploader = 85 BakedTextureUploader uploader =
84 new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener); 86 new BakedTextureUploader(capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_HostCapsObj.AgentID);
85 uploader.OnUpLoad += BakedTextureUploaded; 87 uploader.OnUpLoad += BakedTextureUploaded;
86 88
87 m_HostCapsObj.HttpListener.AddStreamHandler( 89 m_HostCapsObj.HttpListener.AddStreamHandler(
@@ -117,7 +119,7 @@ namespace OpenSim.Capabilities.Handlers
117 /// <param name="data"></param> 119 /// <param name="data"></param>
118 private void BakedTextureUploaded(UUID assetID, byte[] data) 120 private void BakedTextureUploaded(UUID assetID, byte[] data)
119 { 121 {
120// m_log.DebugFormat("[UPLOAD BAKED TEXTURE HANDLER]: Received baked texture {0}", assetID.ToString()); 122 m_log.DebugFormat("[UPLOAD BAKED TEXTURE HANDLER]: Received baked texture {0}", assetID.ToString());
121 123
122 AssetBase asset; 124 AssetBase asset;
123 asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString()); 125 asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString());
@@ -125,6 +127,7 @@ namespace OpenSim.Capabilities.Handlers
125 asset.Temporary = true; 127 asset.Temporary = true;
126 asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are 128 asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are
127 m_assetService.Store(asset); 129 m_assetService.Store(asset);
130
128 } 131 }
129 } 132 }
130 133
@@ -137,15 +140,19 @@ namespace OpenSim.Capabilities.Handlers
137 private string uploaderPath = String.Empty; 140 private string uploaderPath = String.Empty;
138 private UUID newAssetID; 141 private UUID newAssetID;
139 private IHttpServer httpListener; 142 private IHttpServer httpListener;
143 private UUID AgentId = UUID.Zero;
140 144
141 public BakedTextureUploader(string path, IHttpServer httpServer) 145 public BakedTextureUploader(string path, IHttpServer httpServer, UUID uUID)
142 { 146 {
143 newAssetID = UUID.Random(); 147 newAssetID = UUID.Random();
144 uploaderPath = path; 148 uploaderPath = path;
145 httpListener = httpServer; 149 httpListener = httpServer;
150 AgentId = uUID;
146 // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID); 151 // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID);
147 } 152 }
148 153
154
155
149 /// <summary> 156 /// <summary>
150 /// Handle raw uploaded baked texture data. 157 /// Handle raw uploaded baked texture data.
151 /// </summary> 158 /// </summary>
diff --git a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
index ab6cee5..ae8eb09 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadComplete.cs
@@ -30,12 +30,15 @@ using OpenMetaverse;
30 30
31namespace OpenSim.Framework.Capabilities 31namespace OpenSim.Framework.Capabilities
32{ 32{
33
33 [LLSDType("MAP")] 34 [LLSDType("MAP")]
34 public class LLSDAssetUploadComplete 35 public class LLSDAssetUploadComplete
35 { 36 {
36 public string new_asset = String.Empty; 37 public string new_asset = String.Empty;
37 public UUID new_inventory_item = UUID.Zero; 38 public UUID new_inventory_item = UUID.Zero;
39// public UUID new_texture_folder_id = UUID.Zero;
38 public string state = String.Empty; 40 public string state = String.Empty;
41 public LLSDAssetUploadError error = null;
39 //public bool success = false; 42 //public bool success = false;
40 43
41 public LLSDAssetUploadComplete() 44 public LLSDAssetUploadComplete()
diff --git a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
index 6e66f0a..6779cc1 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadRequest.cs
@@ -31,14 +31,27 @@ using OpenMetaverse;
31namespace OpenSim.Framework.Capabilities 31namespace OpenSim.Framework.Capabilities
32{ 32{
33 [OSDMap] 33 [OSDMap]
34 public class LLSDAssetResource
35 {
36 public OSDArray instance_list = new OSDArray();
37 public OSDArray texture_list = new OSDArray();
38 public OSDArray mesh_list = new OSDArray();
39 public string metric = String.Empty;
40 }
41
42 [OSDMap]
34 public class LLSDAssetUploadRequest 43 public class LLSDAssetUploadRequest
35 { 44 {
36 public string asset_type = String.Empty; 45 public string asset_type = String.Empty;
37 public string description = String.Empty; 46 public string description = String.Empty;
38 public UUID folder_id = UUID.Zero; 47 public UUID folder_id = UUID.Zero;
48 public UUID texture_folder_id = UUID.Zero;
49 public int next_owner_mask = 0;
50 public int group_mask = 0;
51 public int everyone_mask = 0;
39 public string inventory_type = String.Empty; 52 public string inventory_type = String.Empty;
40 public string name = String.Empty; 53 public string name = String.Empty;
41 54 public LLSDAssetResource asset_resources = new LLSDAssetResource();
42 public LLSDAssetUploadRequest() 55 public LLSDAssetUploadRequest()
43 { 56 {
44 } 57 }
diff --git a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
index 0d6f7f9..7c4bc97 100644
--- a/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
+++ b/OpenSim/Capabilities/LLSDAssetUploadResponse.cs
@@ -26,20 +26,51 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse;
29 30
30namespace OpenSim.Framework.Capabilities 31namespace OpenSim.Framework.Capabilities
31{ 32{
32 [OSDMap] 33 [OSDMap]
34 public class LLSDAssetUploadError
35 {
36 public string message = String.Empty;
37 public UUID identifier = UUID.Zero;
38 }
39
40 [OSDMap]
41 public class LLSDAssetUploadResponsePricebrkDown
42 {
43 public int mesh_streaming;
44 public int mesh_physics;
45 public int mesh_instance;
46 public int texture;
47 public int model;
48 }
49
50 [OSDMap]
51 public class LLSDAssetUploadResponseData
52 {
53 public double resource_cost;
54 public double model_streaming_cost;
55 public double simulation_cost;
56 public double physics_cost;
57 public LLSDAssetUploadResponsePricebrkDown upload_price_breakdown = new LLSDAssetUploadResponsePricebrkDown();
58 }
59
60 [OSDMap]
33 public class LLSDAssetUploadResponse 61 public class LLSDAssetUploadResponse
34 { 62 {
35 public string uploader = String.Empty; 63 public string uploader = String.Empty;
36 public string state = String.Empty; 64 public string state = String.Empty;
37 65 public int upload_price = 0;
66 public LLSDAssetUploadResponseData data = null;
67 public LLSDAssetUploadError error = null;
38 public LLSDAssetUploadResponse() 68 public LLSDAssetUploadResponse()
39 { 69 {
40 } 70 }
41 } 71 }
42 72
73
43 [OSDMap] 74 [OSDMap]
44 public class LLSDNewFileAngentInventoryVariablePriceReplyResponse 75 public class LLSDNewFileAngentInventoryVariablePriceReplyResponse
45 { 76 {
diff --git a/OpenSim/Data/AssetDataBase.cs b/OpenSim/Data/AssetDataBase.cs
index 1bb432c..9593a25 100644
--- a/OpenSim/Data/AssetDataBase.cs
+++ b/OpenSim/Data/AssetDataBase.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Data
37 public abstract class AssetDataBase : IAssetDataPlugin 37 public abstract class AssetDataBase : IAssetDataPlugin
38 { 38 {
39 public abstract AssetBase GetAsset(UUID uuid); 39 public abstract AssetBase GetAsset(UUID uuid);
40 public abstract void StoreAsset(AssetBase asset); 40 public abstract bool StoreAsset(AssetBase asset);
41 public abstract bool[] AssetsExist(UUID[] uuids); 41 public abstract bool[] AssetsExist(UUID[] uuids);
42 42
43 public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count); 43 public abstract List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
diff --git a/OpenSim/Data/IAssetData.cs b/OpenSim/Data/IAssetData.cs
index a41e310..febab5d 100644
--- a/OpenSim/Data/IAssetData.cs
+++ b/OpenSim/Data/IAssetData.cs
@@ -34,7 +34,7 @@ namespace OpenSim.Data
34 public interface IAssetDataPlugin : IPlugin 34 public interface IAssetDataPlugin : IPlugin
35 { 35 {
36 AssetBase GetAsset(UUID uuid); 36 AssetBase GetAsset(UUID uuid);
37 void StoreAsset(AssetBase asset); 37 bool StoreAsset(AssetBase asset);
38 bool[] AssetsExist(UUID[] uuids); 38 bool[] AssetsExist(UUID[] uuids);
39 List<AssetMetadata> FetchAssetMetadataSet(int start, int count); 39 List<AssetMetadata> FetchAssetMetadataSet(int start, int count);
40 void Initialise(string connect); 40 void Initialise(string connect);
diff --git a/OpenSim/Data/IProfilesData.cs b/OpenSim/Data/IProfilesData.cs
index 7fb075d..a4a32a9 100644
--- a/OpenSim/Data/IProfilesData.cs
+++ b/OpenSim/Data/IProfilesData.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Data
48 bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result); 48 bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result);
49 bool UpdateAvatarInterests(UserProfileProperties up, ref string result); 49 bool UpdateAvatarInterests(UserProfileProperties up, ref string result);
50 bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result); 50 bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result);
51 bool UpdateUserPreferences(ref UserPreferences pref, ref string result); 51 bool UpdateUserPreferences(ref UserPreferences pref, ref string result);
52 bool GetUserPreferences(ref UserPreferences pref, ref string result); 52 bool GetUserPreferences(ref UserPreferences pref, ref string result);
53 bool GetUserAppData(ref UserAppData props, ref string result); 53 bool GetUserAppData(ref UserAppData props, ref string result);
54 bool SetUserAppData(UserAppData props, ref string result); 54 bool SetUserAppData(UserAppData props, ref string result);
diff --git a/OpenSim/Data/IUserAccountData.cs b/OpenSim/Data/IUserAccountData.cs
index 906ba6c..bc7eda7 100644
--- a/OpenSim/Data/IUserAccountData.cs
+++ b/OpenSim/Data/IUserAccountData.cs
@@ -50,5 +50,6 @@ namespace OpenSim.Data
50 bool Store(UserAccountData data); 50 bool Store(UserAccountData data);
51 bool Delete(string field, string val); 51 bool Delete(string field, string val);
52 UserAccountData[] GetUsers(UUID scopeID, string query); 52 UserAccountData[] GetUsers(UUID scopeID, string query);
53 UserAccountData[] GetUsersWhere(UUID scopeID, string where);
53 } 54 }
54} 55}
diff --git a/OpenSim/Data/MySQL/MySQLAgentPreferencesData.cs b/OpenSim/Data/MySQL/MySQLAgentPreferencesData.cs
index ed0ab98..17f1374 100644
--- a/OpenSim/Data/MySQL/MySQLAgentPreferencesData.cs
+++ b/OpenSim/Data/MySQL/MySQLAgentPreferencesData.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 *
diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs
index 5d8da17..1488e1a 100644
--- a/OpenSim/Data/MySQL/MySQLAssetData.cs
+++ b/OpenSim/Data/MySQL/MySQLAssetData.cs
@@ -154,63 +154,59 @@ namespace OpenSim.Data.MySQL
154 /// </summary> 154 /// </summary>
155 /// <param name="asset">Asset UUID to create</param> 155 /// <param name="asset">Asset UUID to create</param>
156 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks> 156 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
157 override public void StoreAsset(AssetBase asset) 157 override public bool StoreAsset(AssetBase asset)
158 { 158 {
159 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 159 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
160 { 160 {
161 dbcon.Open(); 161 dbcon.Open();
162 162
163 string assetName = asset.Name;
164 if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
165 {
166 assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
167 m_log.WarnFormat(
168 "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
169 asset.Name, asset.ID, asset.Name.Length, assetName.Length);
170 }
171
172 string assetDescription = asset.Description;
173 if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
174 {
175 assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
176 m_log.WarnFormat(
177 "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
178 asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
179 }
180
163 using (MySqlCommand cmd = 181 using (MySqlCommand cmd =
164 new MySqlCommand( 182 new MySqlCommand(
165 "replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, asset_flags, CreatorID, data)" + 183 "replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, asset_flags, CreatorID, data)" +
166 "VALUES(?id, ?name, ?description, ?assetType, ?local, ?temporary, ?create_time, ?access_time, ?asset_flags, ?CreatorID, ?data)", 184 "VALUES(?id, ?name, ?description, ?assetType, ?local, ?temporary, ?create_time, ?access_time, ?asset_flags, ?CreatorID, ?data)",
167 dbcon)) 185 dbcon))
168 { 186 {
169 string assetName = asset.Name;
170 if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
171 {
172 assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME);
173 m_log.WarnFormat(
174 "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
175 asset.Name, asset.ID, asset.Name.Length, assetName.Length);
176 }
177
178 string assetDescription = asset.Description;
179 if (asset.Description.Length > AssetBase.MAX_ASSET_DESC)
180 {
181 assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC);
182 m_log.WarnFormat(
183 "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
184 asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
185 }
186
187 try 187 try
188 { 188 {
189 using (cmd) 189 // create unix epoch time
190 { 190 int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
191 // create unix epoch time 191 cmd.Parameters.AddWithValue("?id", asset.ID);
192 int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); 192 cmd.Parameters.AddWithValue("?name", assetName);
193 cmd.Parameters.AddWithValue("?id", asset.ID); 193 cmd.Parameters.AddWithValue("?description", assetDescription);
194 cmd.Parameters.AddWithValue("?name", assetName); 194 cmd.Parameters.AddWithValue("?assetType", asset.Type);
195 cmd.Parameters.AddWithValue("?description", assetDescription); 195 cmd.Parameters.AddWithValue("?local", asset.Local);
196 cmd.Parameters.AddWithValue("?assetType", asset.Type); 196 cmd.Parameters.AddWithValue("?temporary", asset.Temporary);
197 cmd.Parameters.AddWithValue("?local", asset.Local); 197 cmd.Parameters.AddWithValue("?create_time", now);
198 cmd.Parameters.AddWithValue("?temporary", asset.Temporary); 198 cmd.Parameters.AddWithValue("?access_time", now);
199 cmd.Parameters.AddWithValue("?create_time", now); 199 cmd.Parameters.AddWithValue("?CreatorID", asset.Metadata.CreatorID);
200 cmd.Parameters.AddWithValue("?access_time", now); 200 cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags);
201 cmd.Parameters.AddWithValue("?CreatorID", asset.Metadata.CreatorID); 201 cmd.Parameters.AddWithValue("?data", asset.Data);
202 cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags); 202 cmd.ExecuteNonQuery();
203 cmd.Parameters.AddWithValue("?data", asset.Data); 203 return true;
204 cmd.ExecuteNonQuery();
205 }
206 } 204 }
207 catch (Exception e) 205 catch (Exception e)
208 { 206 {
209 m_log.Error( 207 m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}",
210 string.Format( 208 asset.FullID, asset.Name, e.Message);
211 "[ASSET DB]: MySQL failure creating asset {0} with name {1}. Exception ", 209 return false;
212 asset.FullID, asset.Name)
213 , e);
214 } 210 }
215 } 211 }
216 } 212 }
@@ -227,21 +223,18 @@ namespace OpenSim.Data.MySQL
227 { 223 {
228 try 224 try
229 { 225 {
230 using (cmd) 226 // create unix epoch time
231 { 227 int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
232 // create unix epoch time 228 cmd.Parameters.AddWithValue("?id", asset.ID);
233 int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); 229 cmd.Parameters.AddWithValue("?access_time", now);
234 cmd.Parameters.AddWithValue("?id", asset.ID); 230 cmd.ExecuteNonQuery();
235 cmd.Parameters.AddWithValue("?access_time", now);
236 cmd.ExecuteNonQuery();
237 }
238 } 231 }
239 catch (Exception e) 232 catch (Exception e)
240 { 233 {
241 m_log.Error( 234 m_log.Error(
242 string.Format( 235 string.Format(
243 "[ASSETS DB]: Failure updating access_time for asset {0} with name {1}. Exception ", 236 "[ASSETS DB]: Failure updating access_time for asset {0} with name {1}. Exception ",
244 asset.FullID, asset.Name), 237 asset.FullID, asset.Name),
245 e); 238 e);
246 } 239 }
247 } 240 }
@@ -364,4 +357,4 @@ namespace OpenSim.Data.MySQL
364 357
365 #endregion 358 #endregion
366 } 359 }
367} \ No newline at end of file 360}
diff --git a/OpenSim/Data/MySQL/MySQLFramework.cs b/OpenSim/Data/MySQL/MySQLFramework.cs
index 5820a90..34791cf 100644
--- a/OpenSim/Data/MySQL/MySQLFramework.cs
+++ b/OpenSim/Data/MySQL/MySQLFramework.cs
@@ -45,27 +45,45 @@ namespace OpenSim.Data.MySQL
45 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 45 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 protected string m_connectionString; 47 protected string m_connectionString;
48 protected object m_dbLock = new object();
48 49
49 protected MySqlFramework(string connectionString) 50 protected MySqlFramework(string connectionString)
50 { 51 {
51 m_connectionString = connectionString; 52 m_connectionString = connectionString;
52 } 53 }
53 54
55 //////////////////////////////////////////////////////////////
56 //
57 // All non queries are funneled through one connection
58 // to increase performance a little
59 //
54 protected int ExecuteNonQuery(MySqlCommand cmd) 60 protected int ExecuteNonQuery(MySqlCommand cmd)
55 { 61 {
56 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 62 lock (m_dbLock)
57 { 63 {
58 dbcon.Open(); 64 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
59 cmd.Connection = dbcon;
60
61 try
62 {
63 return cmd.ExecuteNonQuery();
64 }
65 catch (Exception e)
66 { 65 {
67 m_log.Error(e.Message, e); 66 try
68 return 0; 67 {
68 dbcon.Open();
69 cmd.Connection = dbcon;
70
71 try
72 {
73 return cmd.ExecuteNonQuery();
74 }
75 catch (Exception e)
76 {
77 m_log.Error(e.Message, e);
78 m_log.Error(Environment.StackTrace.ToString());
79 return 0;
80 }
81 }
82 catch (Exception e)
83 {
84 m_log.Error(e.Message, e);
85 return 0;
86 }
69 } 87 }
70 } 88 }
71 } 89 }
diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
index 35fa89f..dc657c8 100644
--- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
+++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
@@ -175,6 +175,11 @@ namespace OpenSim.Data.MySQL
175 int v = Convert.ToInt32(reader[name]); 175 int v = Convert.ToInt32(reader[name]);
176 m_Fields[name].SetValue(row, v); 176 m_Fields[name].SetValue(row, v);
177 } 177 }
178 else if (m_Fields[name].FieldType == typeof(uint))
179 {
180 uint v = Convert.ToUInt32(reader[name]);
181 m_Fields[name].SetValue(row, v);
182 }
178 else 183 else
179 { 184 {
180 m_Fields[name].SetValue(row, reader[name]); 185 m_Fields[name].SetValue(row, reader[name]);
@@ -362,4 +367,4 @@ namespace OpenSim.Data.MySQL
362 } 367 }
363 368
364 } 369 }
365} \ No newline at end of file 370}
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index 2ad7590..3dc049b 100644
--- a/OpenSim/Data/MySQL/MySQLRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLRegionData.cs
@@ -82,6 +82,7 @@ namespace OpenSim.Data.MySQL
82 82
83 public RegionData Get(int posX, int posY, UUID scopeID) 83 public RegionData Get(int posX, int posY, UUID scopeID)
84 { 84 {
85/* fixed size regions
85 string command = "select * from `"+m_Realm+"` where locX = ?posX and locY = ?posY"; 86 string command = "select * from `"+m_Realm+"` where locX = ?posX and locY = ?posY";
86 if (scopeID != UUID.Zero) 87 if (scopeID != UUID.Zero)
87 command += " and ScopeID = ?scopeID"; 88 command += " and ScopeID = ?scopeID";
@@ -98,6 +99,45 @@ namespace OpenSim.Data.MySQL
98 99
99 return ret[0]; 100 return ret[0];
100 } 101 }
102*/
103 // extend database search for maximum region size area
104 string command = "select * from `" + m_Realm + "` where locX between ?startX and ?endX and locY between ?startY and ?endY";
105 if (scopeID != UUID.Zero)
106 command += " and ScopeID = ?scopeID";
107
108 int startX = posX - (int)Constants.MaximumRegionSize;
109 int startY = posY - (int)Constants.MaximumRegionSize;
110 int endX = posX;
111 int endY = posY;
112
113 List<RegionData> ret;
114 using (MySqlCommand cmd = new MySqlCommand(command))
115 {
116 cmd.Parameters.AddWithValue("?startX", startX.ToString());
117 cmd.Parameters.AddWithValue("?startY", startY.ToString());
118 cmd.Parameters.AddWithValue("?endX", endX.ToString());
119 cmd.Parameters.AddWithValue("?endY", endY.ToString());
120 cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
121
122 ret = RunCommand(cmd);
123 }
124
125 if (ret.Count == 0)
126 return null;
127
128 // find the first that contains pos
129 RegionData rg = null;
130 foreach (RegionData r in ret)
131 {
132 if (posX >= r.posX && posX < r.posX + r.sizeX
133 && posY >= r.posY && posY < r.posY + r.sizeY)
134 {
135 rg = r;
136 break;
137 }
138 }
139
140 return rg;
101 } 141 }
102 142
103 public RegionData Get(UUID regionID, UUID scopeID) 143 public RegionData Get(UUID regionID, UUID scopeID)
@@ -121,6 +161,7 @@ namespace OpenSim.Data.MySQL
121 161
122 public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID) 162 public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID)
123 { 163 {
164/* fix size regions
124 string command = "select * from `"+m_Realm+"` where locX between ?startX and ?endX and locY between ?startY and ?endY"; 165 string command = "select * from `"+m_Realm+"` where locX between ?startX and ?endX and locY between ?startY and ?endY";
125 if (scopeID != UUID.Zero) 166 if (scopeID != UUID.Zero)
126 command += " and ScopeID = ?scopeID"; 167 command += " and ScopeID = ?scopeID";
@@ -135,6 +176,38 @@ namespace OpenSim.Data.MySQL
135 176
136 return RunCommand(cmd); 177 return RunCommand(cmd);
137 } 178 }
179 */
180 string command = "select * from `" + m_Realm + "` where locX between ?startX and ?endX and locY between ?startY and ?endY";
181 if (scopeID != UUID.Zero)
182 command += " and ScopeID = ?scopeID";
183
184 int qstartX = startX - (int)Constants.MaximumRegionSize;
185 int qstartY = startY - (int)Constants.MaximumRegionSize;
186
187 List<RegionData> dbret;
188 using (MySqlCommand cmd = new MySqlCommand(command))
189 {
190 cmd.Parameters.AddWithValue("?startX", qstartX.ToString());
191 cmd.Parameters.AddWithValue("?startY", qstartY.ToString());
192 cmd.Parameters.AddWithValue("?endX", endX.ToString());
193 cmd.Parameters.AddWithValue("?endY", endY.ToString());
194 cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
195
196 dbret = RunCommand(cmd);
197 }
198
199 List<RegionData> ret = new List<RegionData>();
200
201 if (dbret.Count == 0)
202 return ret;
203
204 foreach (RegionData r in dbret)
205 {
206 if (r.posX + r.sizeX > startX && r.posX <= endX
207 && r.posY + r.sizeX > startY && r.posY <= endY)
208 ret.Add(r);
209 }
210 return ret;
138 } 211 }
139 212
140 public List<RegionData> RunCommand(MySqlCommand cmd) 213 public List<RegionData> RunCommand(MySqlCommand cmd)
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index bb0ab75..46364a5 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Data.MySQL
76 Initialise(connectionString); 76 Initialise(connectionString);
77 } 77 }
78 78
79 public void Initialise(string connectionString) 79 public virtual void Initialise(string connectionString)
80 { 80 {
81 m_connectionString = connectionString; 81 m_connectionString = connectionString;
82 82
@@ -123,7 +123,7 @@ namespace OpenSim.Data.MySQL
123 123
124 public void Dispose() {} 124 public void Dispose() {}
125 125
126 public void StoreObject(SceneObjectGroup obj, UUID regionUUID) 126 public virtual void StoreObject(SceneObjectGroup obj, UUID regionUUID)
127 { 127 {
128 uint flags = obj.RootPart.GetEffectiveObjectFlags(); 128 uint flags = obj.RootPart.GetEffectiveObjectFlags();
129 129
@@ -183,10 +183,12 @@ namespace OpenSim.Data.MySQL
183 "ParticleSystem, ClickAction, Material, " + 183 "ParticleSystem, ClickAction, Material, " +
184 "CollisionSound, CollisionSoundVolume, " + 184 "CollisionSound, CollisionSoundVolume, " +
185 "PassTouches, " + 185 "PassTouches, " +
186 "LinkNumber, MediaURL, AttachedPosX, " + 186 "PassCollisions, " +
187 "AttachedPosY, AttachedPosZ, KeyframeMotion, " + 187 "LinkNumber, MediaURL, KeyframeMotion, AttachedPosX, " +
188 "AttachedPosY, AttachedPosZ, " +
188 "PhysicsShapeType, Density, GravityModifier, " + 189 "PhysicsShapeType, Density, GravityModifier, " +
189 "Friction, Restitution, DynAttrs " + 190 "Friction, Restitution, Vehicle, DynAttrs, " +
191 "RotationAxisLocks" +
190 ") values (" + "?UUID, " + 192 ") values (" + "?UUID, " +
191 "?CreationDate, ?Name, ?Text, " + 193 "?CreationDate, ?Name, ?Text, " +
192 "?Description, ?SitName, ?TouchName, " + 194 "?Description, ?SitName, ?TouchName, " +
@@ -218,11 +220,12 @@ namespace OpenSim.Data.MySQL
218 "?SaleType, ?ColorR, ?ColorG, " + 220 "?SaleType, ?ColorR, ?ColorG, " +
219 "?ColorB, ?ColorA, ?ParticleSystem, " + 221 "?ColorB, ?ColorA, ?ParticleSystem, " +
220 "?ClickAction, ?Material, ?CollisionSound, " + 222 "?ClickAction, ?Material, ?CollisionSound, " +
221 "?CollisionSoundVolume, ?PassTouches, " + 223 "?CollisionSoundVolume, ?PassTouches, ?PassCollisions, " +
222 "?LinkNumber, ?MediaURL, ?AttachedPosX, " + 224 "?LinkNumber, ?MediaURL, ?KeyframeMotion, ?AttachedPosX, " +
223 "?AttachedPosY, ?AttachedPosZ, ?KeyframeMotion, " + 225 "?AttachedPosY, ?AttachedPosZ, " +
224 "?PhysicsShapeType, ?Density, ?GravityModifier, " + 226 "?PhysicsShapeType, ?Density, ?GravityModifier, " +
225 "?Friction, ?Restitution, ?DynAttrs)"; 227 "?Friction, ?Restitution, ?Vehicle, ?DynAttrs," +
228 "?RotationAxisLocks)";
226 229
227 FillPrimCommand(cmd, prim, obj.UUID, regionUUID); 230 FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
228 231
@@ -262,7 +265,7 @@ namespace OpenSim.Data.MySQL
262 } 265 }
263 } 266 }
264 267
265 public void RemoveObject(UUID obj, UUID regionUUID) 268 public virtual void RemoveObject(UUID obj, UUID regionUUID)
266 { 269 {
267// m_log.DebugFormat("[REGION DB]: Deleting scene object {0} from {1} in database", obj, regionUUID); 270// m_log.DebugFormat("[REGION DB]: Deleting scene object {0} from {1} in database", obj, regionUUID);
268 271
@@ -317,7 +320,8 @@ namespace OpenSim.Data.MySQL
317 /// <param name="uuid">the Item UUID</param> 320 /// <param name="uuid">the Item UUID</param>
318 private void RemoveItems(UUID uuid) 321 private void RemoveItems(UUID uuid)
319 { 322 {
320 lock (m_dbLock) 323 // locked by caller
324// lock (m_dbLock)
321 { 325 {
322 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 326 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
323 { 327 {
@@ -411,7 +415,7 @@ namespace OpenSim.Data.MySQL
411 } 415 }
412 } 416 }
413 417
414 public List<SceneObjectGroup> LoadObjects(UUID regionID) 418 public virtual List<SceneObjectGroup> LoadObjects(UUID regionID)
415 { 419 {
416 const int ROWS_PER_QUERY = 5000; 420 const int ROWS_PER_QUERY = 5000;
417 421
@@ -590,40 +594,53 @@ namespace OpenSim.Data.MySQL
590 594
591 public void StoreTerrain(TerrainData terrData, UUID regionID) 595 public void StoreTerrain(TerrainData terrData, UUID regionID)
592 { 596 {
593 lock (m_dbLock) 597 Util.FireAndForget(delegate(object x)
594 { 598 {
595 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 599 m_log.Info("[REGION DB]: Storing terrain");
596 {
597 dbcon.Open();
598 600
599 using (MySqlCommand cmd = dbcon.CreateCommand()) 601 lock (m_dbLock)
602 {
603 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
600 { 604 {
601 cmd.CommandText = "delete from terrain where RegionUUID = ?RegionUUID"; 605 dbcon.Open();
602 cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
603
604 ExecuteNonQuery(cmd);
605 606
606 int terrainDBRevision; 607 using (MySqlCommand cmd = dbcon.CreateCommand())
607 Array terrainDBblob; 608 {
608 terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); 609 cmd.CommandText = "delete from terrain where RegionUUID = ?RegionUUID";
610 cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
609 611
610 m_log.InfoFormat("{0} Storing terrain. X={1}, Y={2}, rev={3}", 612 using (MySqlCommand cmd2 = dbcon.CreateCommand())
611 LogHeader, terrData.SizeX, terrData.SizeY, terrainDBRevision); 613 {
614 try
615 {
616 cmd2.CommandText = "insert into terrain (RegionUUID, " +
617 "Revision, Heightfield) values (?RegionUUID, " +
618 "?Revision, ?Heightfield)";
612 619
613 cmd.CommandText = "insert into terrain (RegionUUID, Revision, Heightfield)" 620 int terrainDBRevision;
614 + "values (?RegionUUID, ?Revision, ?Heightfield)"; 621 Array terrainDBblob;
622 terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob);
615 623
616 cmd.Parameters.AddWithValue("Revision", terrainDBRevision); 624 cmd2.Parameters.AddWithValue("RegionUUID", regionID.ToString());
617 cmd.Parameters.AddWithValue("Heightfield", terrainDBblob); 625 cmd2.Parameters.AddWithValue("Revision", terrainDBRevision);
626 cmd2.Parameters.AddWithValue("Heightfield", terrainDBblob);
618 627
619 ExecuteNonQuery(cmd); 628 ExecuteNonQuery(cmd);
629 ExecuteNonQuery(cmd2);
630 }
631 catch (Exception e)
632 {
633 m_log.ErrorFormat(e.ToString());
634 }
635 }
636 }
620 } 637 }
621 } 638 }
622 } 639 });
623 } 640 }
624 641
625 // Legacy region loading 642 // Legacy region loading
626 public double[,] LoadTerrain(UUID regionID) 643 public virtual double[,] LoadTerrain(UUID regionID)
627 { 644 {
628 double[,] ret = null; 645 double[,] ret = null;
629 TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight); 646 TerrainData terrData = LoadTerrain(regionID, (int)Constants.RegionSize, (int)Constants.RegionSize, (int)Constants.RegionHeight);
@@ -655,8 +672,11 @@ namespace OpenSim.Data.MySQL
655 while (reader.Read()) 672 while (reader.Read())
656 { 673 {
657 int rev = Convert.ToInt32(reader["Revision"]); 674 int rev = Convert.ToInt32(reader["Revision"]);
658 byte[] blob = (byte[])reader["Heightfield"]; 675 if ((reader["Heightfield"] != DBNull.Value))
659 terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); 676 {
677 byte[] blob = (byte[])reader["Heightfield"];
678 terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob);
679 }
660 } 680 }
661 } 681 }
662 } 682 }
@@ -666,7 +686,7 @@ namespace OpenSim.Data.MySQL
666 return terrData; 686 return terrData;
667 } 687 }
668 688
669 public void RemoveLandObject(UUID globalID) 689 public virtual void RemoveLandObject(UUID globalID)
670 { 690 {
671 lock (m_dbLock) 691 lock (m_dbLock)
672 { 692 {
@@ -685,7 +705,7 @@ namespace OpenSim.Data.MySQL
685 } 705 }
686 } 706 }
687 707
688 public void StoreLandObject(ILandObject parcel) 708 public virtual void StoreLandObject(ILandObject parcel)
689 { 709 {
690 lock (m_dbLock) 710 lock (m_dbLock)
691 { 711 {
@@ -705,7 +725,8 @@ namespace OpenSim.Data.MySQL
705 "UserLocationX, UserLocationY, UserLocationZ, " + 725 "UserLocationX, UserLocationY, UserLocationZ, " +
706 "UserLookAtX, UserLookAtY, UserLookAtZ, " + 726 "UserLookAtX, UserLookAtY, UserLookAtZ, " +
707 "AuthbuyerID, OtherCleanTime, Dwell, MediaType, MediaDescription, " + 727 "AuthbuyerID, OtherCleanTime, Dwell, MediaType, MediaDescription, " +
708 "MediaSize, MediaLoop, ObscureMusic, ObscureMedia) values (" + 728 "MediaSize, MediaLoop, ObscureMusic, ObscureMedia, " +
729 "SeeAVs, AnyAVSounds, GroupAVSounds) values (" +
709 "?UUID, ?RegionUUID, " + 730 "?UUID, ?RegionUUID, " +
710 "?LocalLandID, ?Bitmap, ?Name, ?Description, " + 731 "?LocalLandID, ?Bitmap, ?Name, ?Description, " +
711 "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " + 732 "?OwnerUUID, ?IsGroupOwned, ?Area, ?AuctionID, " +
@@ -716,7 +737,8 @@ namespace OpenSim.Data.MySQL
716 "?UserLocationX, ?UserLocationY, ?UserLocationZ, " + 737 "?UserLocationX, ?UserLocationY, ?UserLocationZ, " +
717 "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " + 738 "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " +
718 "?AuthbuyerID, ?OtherCleanTime, ?Dwell, ?MediaType, ?MediaDescription, "+ 739 "?AuthbuyerID, ?OtherCleanTime, ?Dwell, ?MediaType, ?MediaDescription, "+
719 "CONCAT(?MediaWidth, ',', ?MediaHeight), ?MediaLoop, ?ObscureMusic, ?ObscureMedia)"; 740 "CONCAT(?MediaWidth, ',', ?MediaHeight), ?MediaLoop, ?ObscureMusic, ?ObscureMedia, " +
741 "?SeeAVs, ?AnyAVSounds, ?GroupAVSounds)";
720 742
721 FillLandCommand(cmd, parcel.LandData, parcel.RegionUUID); 743 FillLandCommand(cmd, parcel.LandData, parcel.RegionUUID);
722 744
@@ -742,7 +764,7 @@ namespace OpenSim.Data.MySQL
742 } 764 }
743 } 765 }
744 766
745 public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) 767 public virtual RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
746 { 768 {
747 RegionLightShareData nWP = new RegionLightShareData(); 769 RegionLightShareData nWP = new RegionLightShareData();
748 nWP.OnSave += StoreRegionWindlightSettings; 770 nWP.OnSave += StoreRegionWindlightSettings;
@@ -840,7 +862,7 @@ namespace OpenSim.Data.MySQL
840 return nWP; 862 return nWP;
841 } 863 }
842 864
843 public RegionSettings LoadRegionSettings(UUID regionUUID) 865 public virtual RegionSettings LoadRegionSettings(UUID regionUUID)
844 { 866 {
845 RegionSettings rs = null; 867 RegionSettings rs = null;
846 868
@@ -880,7 +902,7 @@ namespace OpenSim.Data.MySQL
880 return rs; 902 return rs;
881 } 903 }
882 904
883 public void StoreRegionWindlightSettings(RegionLightShareData wl) 905 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl)
884 { 906 {
885 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 907 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
886 { 908 {
@@ -983,7 +1005,7 @@ namespace OpenSim.Data.MySQL
983 } 1005 }
984 } 1006 }
985 1007
986 public void RemoveRegionWindlightSettings(UUID regionID) 1008 public virtual void RemoveRegionWindlightSettings(UUID regionID)
987 { 1009 {
988 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1010 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
989 { 1011 {
@@ -1060,7 +1082,7 @@ namespace OpenSim.Data.MySQL
1060 } 1082 }
1061 #endregion 1083 #endregion
1062 1084
1063 public void StoreRegionSettings(RegionSettings rs) 1085 public virtual void StoreRegionSettings(RegionSettings rs)
1064 { 1086 {
1065 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1087 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1066 { 1088 {
@@ -1069,52 +1091,51 @@ namespace OpenSim.Data.MySQL
1069 using (MySqlCommand cmd = dbcon.CreateCommand()) 1091 using (MySqlCommand cmd = dbcon.CreateCommand())
1070 { 1092 {
1071 cmd.CommandText = "replace into regionsettings (regionUUID, " + 1093 cmd.CommandText = "replace into regionsettings (regionUUID, " +
1072 "block_terraform, block_fly, allow_damage, " + 1094 "block_terraform, block_fly, allow_damage, " +
1073 "restrict_pushing, allow_land_resell, " + 1095 "restrict_pushing, allow_land_resell, " +
1074 "allow_land_join_divide, block_show_in_search, " + 1096 "allow_land_join_divide, block_show_in_search, " +
1075 "agent_limit, object_bonus, maturity, " + 1097 "agent_limit, object_bonus, maturity, " +
1076 "disable_scripts, disable_collisions, " + 1098 "disable_scripts, disable_collisions, " +
1077 "disable_physics, terrain_texture_1, " + 1099 "disable_physics, terrain_texture_1, " +
1078 "terrain_texture_2, terrain_texture_3, " + 1100 "terrain_texture_2, terrain_texture_3, " +
1079 "terrain_texture_4, elevation_1_nw, " + 1101 "terrain_texture_4, elevation_1_nw, " +
1080 "elevation_2_nw, elevation_1_ne, " + 1102 "elevation_2_nw, elevation_1_ne, " +
1081 "elevation_2_ne, elevation_1_se, " + 1103 "elevation_2_ne, elevation_1_se, " +
1082 "elevation_2_se, elevation_1_sw, " + 1104 "elevation_2_se, elevation_1_sw, " +
1083 "elevation_2_sw, water_height, " + 1105 "elevation_2_sw, water_height, " +
1084 "terrain_raise_limit, terrain_lower_limit, " + 1106 "terrain_raise_limit, terrain_lower_limit, " +
1085 "use_estate_sun, fixed_sun, sun_position, " + 1107 "use_estate_sun, fixed_sun, sun_position, " +
1086 "covenant, covenant_datetime, Sandbox, sunvectorx, sunvectory, " + 1108 "covenant, covenant_datetime, Sandbox, sunvectorx, sunvectory, " +
1087 "sunvectorz, loaded_creation_datetime, " + 1109 "sunvectorz, loaded_creation_datetime, " +
1088 "loaded_creation_id, map_tile_ID, " + 1110 "loaded_creation_id, map_tile_ID, block_search, casino, " +
1089 "TelehubObject, parcel_tile_ID) " + 1111 "TelehubObject, parcel_tile_ID) " +
1090 "values (?RegionUUID, ?BlockTerraform, " + 1112 "values (?RegionUUID, ?BlockTerraform, " +
1091 "?BlockFly, ?AllowDamage, ?RestrictPushing, " + 1113 "?BlockFly, ?AllowDamage, ?RestrictPushing, " +
1092 "?AllowLandResell, ?AllowLandJoinDivide, " + 1114 "?AllowLandResell, ?AllowLandJoinDivide, " +
1093 "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " + 1115 "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " +
1094 "?Maturity, ?DisableScripts, ?DisableCollisions, " + 1116 "?Maturity, ?DisableScripts, ?DisableCollisions, " +
1095 "?DisablePhysics, ?TerrainTexture1, " + 1117 "?DisablePhysics, ?TerrainTexture1, " +
1096 "?TerrainTexture2, ?TerrainTexture3, " + 1118 "?TerrainTexture2, ?TerrainTexture3, " +
1097 "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " + 1119 "?TerrainTexture4, ?Elevation1NW, ?Elevation2NW, " +
1098 "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " + 1120 "?Elevation1NE, ?Elevation2NE, ?Elevation1SE, " +
1099 "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " + 1121 "?Elevation2SE, ?Elevation1SW, ?Elevation2SW, " +
1100 "?WaterHeight, ?TerrainRaiseLimit, " + 1122 "?WaterHeight, ?TerrainRaiseLimit, " +
1101 "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " + 1123 "?TerrainLowerLimit, ?UseEstateSun, ?FixedSun, " +
1102 "?SunPosition, ?Covenant, ?CovenantChangedDateTime, ?Sandbox, " + 1124 "?SunPosition, ?Covenant, ?CovenantChangedDateTime, ?Sandbox, " +
1103 "?SunVectorX, ?SunVectorY, ?SunVectorZ, " + 1125 "?SunVectorX, ?SunVectorY, ?SunVectorZ, " +
1104 "?LoadedCreationDateTime, ?LoadedCreationID, " + 1126 "?LoadedCreationDateTime, ?LoadedCreationID, " +
1105 "?TerrainImageID, " + 1127 "?TerrainImageID, ?block_search, ?casino, " +
1106 "?TelehubObject, ?ParcelImageID)"; 1128 "?TelehubObject, ?ParcelImageID)";
1107 1129
1108 FillRegionSettingsCommand(cmd, rs); 1130 FillRegionSettingsCommand(cmd, rs);
1109
1110 ExecuteNonQuery(cmd); 1131 ExecuteNonQuery(cmd);
1111 } 1132 }
1112 }
1113 1133
1114 SaveSpawnPoints(rs); 1134 SaveSpawnPoints(rs);
1135 }
1115 } 1136 }
1116 1137
1117 public List<LandData> LoadLandObjects(UUID regionUUID) 1138 public virtual List<LandData> LoadLandObjects(UUID regionUUID)
1118 { 1139 {
1119 List<LandData> landData = new List<LandData>(); 1140 List<LandData> landData = new List<LandData>();
1120 1141
@@ -1296,6 +1317,7 @@ namespace OpenSim.Data.MySQL
1296 prim.CollisionSoundVolume = (float)(double)row["CollisionSoundVolume"]; 1317 prim.CollisionSoundVolume = (float)(double)row["CollisionSoundVolume"];
1297 1318
1298 prim.PassTouches = ((sbyte)row["PassTouches"] != 0); 1319 prim.PassTouches = ((sbyte)row["PassTouches"] != 0);
1320 prim.PassCollisions = ((sbyte)row["PassCollisions"] != 0);
1299 prim.LinkNum = (int)row["LinkNumber"]; 1321 prim.LinkNum = (int)row["LinkNumber"];
1300 1322
1301 if (!(row["MediaURL"] is System.DBNull)) 1323 if (!(row["MediaURL"] is System.DBNull))
@@ -1333,7 +1355,17 @@ namespace OpenSim.Data.MySQL
1333 prim.GravityModifier = (float)(double)row["GravityModifier"]; 1355 prim.GravityModifier = (float)(double)row["GravityModifier"];
1334 prim.Friction = (float)(double)row["Friction"]; 1356 prim.Friction = (float)(double)row["Friction"];
1335 prim.Restitution = (float)(double)row["Restitution"]; 1357 prim.Restitution = (float)(double)row["Restitution"];
1336 1358 prim.RotationAxisLocks = (byte)Convert.ToInt32(row["RotationAxisLocks"].ToString());
1359
1360 SOPVehicle vehicle = null;
1361
1362 if (row["Vehicle"].ToString() != String.Empty)
1363 {
1364 vehicle = SOPVehicle.FromXml2(row["Vehicle"].ToString());
1365 if (vehicle != null)
1366 prim.VehicleParams = vehicle;
1367 }
1368
1337 return prim; 1369 return prim;
1338 } 1370 }
1339 1371
@@ -1344,32 +1376,40 @@ namespace OpenSim.Data.MySQL
1344 /// <returns></returns> 1376 /// <returns></returns>
1345 private static TaskInventoryItem BuildItem(IDataReader row) 1377 private static TaskInventoryItem BuildItem(IDataReader row)
1346 { 1378 {
1347 TaskInventoryItem taskItem = new TaskInventoryItem(); 1379 try
1348 1380 {
1349 taskItem.ItemID = DBGuid.FromDB(row["itemID"]); 1381 TaskInventoryItem taskItem = new TaskInventoryItem();
1350 taskItem.ParentPartID = DBGuid.FromDB(row["primID"]); 1382
1351 taskItem.AssetID = DBGuid.FromDB(row["assetID"]); 1383 taskItem.ItemID = DBGuid.FromDB(row["itemID"]);
1352 taskItem.ParentID = DBGuid.FromDB(row["parentFolderID"]); 1384 taskItem.ParentPartID = DBGuid.FromDB(row["primID"]);
1353 1385 taskItem.AssetID = DBGuid.FromDB(row["assetID"]);
1354 taskItem.InvType = Convert.ToInt32(row["invType"]); 1386 taskItem.ParentID = DBGuid.FromDB(row["parentFolderID"]);
1355 taskItem.Type = Convert.ToInt32(row["assetType"]); 1387
1356 1388 taskItem.InvType = Convert.ToInt32(row["invType"]);
1357 taskItem.Name = (String)row["name"]; 1389 taskItem.Type = Convert.ToInt32(row["assetType"]);
1358 taskItem.Description = (String)row["description"]; 1390
1359 taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); 1391 taskItem.Name = (String)row["name"];
1360 taskItem.CreatorIdentification = (String)row["creatorID"]; 1392 taskItem.Description = (String)row["description"];
1361 taskItem.OwnerID = DBGuid.FromDB(row["ownerID"]); 1393 taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]);
1362 taskItem.LastOwnerID = DBGuid.FromDB(row["lastOwnerID"]); 1394 taskItem.CreatorIdentification = (String)row["creatorID"];
1363 taskItem.GroupID = DBGuid.FromDB(row["groupID"]); 1395 taskItem.OwnerID = DBGuid.FromDB(row["ownerID"]);
1364 1396 taskItem.LastOwnerID = DBGuid.FromDB(row["lastOwnerID"]);
1365 taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); 1397 taskItem.GroupID = DBGuid.FromDB(row["groupID"]);
1366 taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); 1398
1367 taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); 1399 taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]);
1368 taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); 1400 taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]);
1369 taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); 1401 taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]);
1370 taskItem.Flags = Convert.ToUInt32(row["flags"]); 1402 taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]);
1371 1403 taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]);
1372 return taskItem; 1404 taskItem.Flags = Convert.ToUInt32(row["flags"]);
1405
1406 return taskItem;
1407 }
1408 catch
1409 {
1410 m_log.ErrorFormat("[MYSQL DB]: Error reading task inventory: itemID was {0}, primID was {1}", row["itemID"].ToString(), row["primID"].ToString());
1411 throw;
1412 }
1373 } 1413 }
1374 1414
1375 private static RegionSettings BuildRegionSettings(IDataReader row) 1415 private static RegionSettings BuildRegionSettings(IDataReader row)
@@ -1427,6 +1467,9 @@ namespace OpenSim.Data.MySQL
1427 newSettings.ParcelImageID = DBGuid.FromDB(row["parcel_tile_ID"]); 1467 newSettings.ParcelImageID = DBGuid.FromDB(row["parcel_tile_ID"]);
1428 newSettings.TelehubObject = DBGuid.FromDB(row["TelehubObject"]); 1468 newSettings.TelehubObject = DBGuid.FromDB(row["TelehubObject"]);
1429 1469
1470 newSettings.GodBlockSearch = Convert.ToBoolean(row["block_search"]);
1471 newSettings.Casino = Convert.ToBoolean(row["casino"]);
1472
1430 return newSettings; 1473 return newSettings;
1431 } 1474 }
1432 1475
@@ -1503,6 +1546,13 @@ namespace OpenSim.Data.MySQL
1503 1546
1504 newData.ParcelAccessList = new List<LandAccessEntry>(); 1547 newData.ParcelAccessList = new List<LandAccessEntry>();
1505 1548
1549 if (!(row["SeeAVs"] is System.DBNull))
1550 newData.SeeAVs = Convert.ToInt32(row["SeeAVs"]) != 0 ? true : false;
1551 if (!(row["AnyAVSounds"] is System.DBNull))
1552 newData.AnyAVSounds = Convert.ToInt32(row["AnyAVSounds"]) != 0 ? true : false;
1553 if (!(row["GroupAVSounds"] is System.DBNull))
1554 newData.GroupAVSounds = Convert.ToInt32(row["GroupAVSounds"]) != 0 ? true : false;
1555
1506 return newData; 1556 return newData;
1507 } 1557 }
1508 1558
@@ -1654,6 +1704,11 @@ namespace OpenSim.Data.MySQL
1654 else 1704 else
1655 cmd.Parameters.AddWithValue("PassTouches", 0); 1705 cmd.Parameters.AddWithValue("PassTouches", 0);
1656 1706
1707 if (prim.PassCollisions)
1708 cmd.Parameters.AddWithValue("PassCollisions", 1);
1709 else
1710 cmd.Parameters.AddWithValue("PassCollisions", 0);
1711
1657 cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum); 1712 cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
1658 cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl); 1713 cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl);
1659 if (prim.AttachedPos != null) 1714 if (prim.AttachedPos != null)
@@ -1668,6 +1723,11 @@ namespace OpenSim.Data.MySQL
1668 else 1723 else
1669 cmd.Parameters.AddWithValue("KeyframeMotion", new Byte[0]); 1724 cmd.Parameters.AddWithValue("KeyframeMotion", new Byte[0]);
1670 1725
1726 if (prim.VehicleParams != null)
1727 cmd.Parameters.AddWithValue("Vehicle", prim.VehicleParams.ToXml2());
1728 else
1729 cmd.Parameters.AddWithValue("Vehicle", String.Empty);
1730
1671 if (prim.DynAttrs.CountNamespaces > 0) 1731 if (prim.DynAttrs.CountNamespaces > 0)
1672 cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml()); 1732 cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml());
1673 else 1733 else
@@ -1678,6 +1738,7 @@ namespace OpenSim.Data.MySQL
1678 cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier); 1738 cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier);
1679 cmd.Parameters.AddWithValue("Friction", (double)prim.Friction); 1739 cmd.Parameters.AddWithValue("Friction", (double)prim.Friction);
1680 cmd.Parameters.AddWithValue("Restitution", (double)prim.Restitution); 1740 cmd.Parameters.AddWithValue("Restitution", (double)prim.Restitution);
1741 cmd.Parameters.AddWithValue("RotationAxisLocks", prim.RotationAxisLocks);
1681 } 1742 }
1682 1743
1683 /// <summary> 1744 /// <summary>
@@ -1756,6 +1817,8 @@ namespace OpenSim.Data.MySQL
1756 cmd.Parameters.AddWithValue("LoadedCreationDateTime", settings.LoadedCreationDateTime); 1817 cmd.Parameters.AddWithValue("LoadedCreationDateTime", settings.LoadedCreationDateTime);
1757 cmd.Parameters.AddWithValue("LoadedCreationID", settings.LoadedCreationID); 1818 cmd.Parameters.AddWithValue("LoadedCreationID", settings.LoadedCreationID);
1758 cmd.Parameters.AddWithValue("TerrainImageID", settings.TerrainImageID); 1819 cmd.Parameters.AddWithValue("TerrainImageID", settings.TerrainImageID);
1820 cmd.Parameters.AddWithValue("block_search", settings.GodBlockSearch);
1821 cmd.Parameters.AddWithValue("casino", settings.Casino);
1759 1822
1760 cmd.Parameters.AddWithValue("ParcelImageID", settings.ParcelImageID); 1823 cmd.Parameters.AddWithValue("ParcelImageID", settings.ParcelImageID);
1761 cmd.Parameters.AddWithValue("TelehubObject", settings.TelehubObject); 1824 cmd.Parameters.AddWithValue("TelehubObject", settings.TelehubObject);
@@ -1813,6 +1876,10 @@ namespace OpenSim.Data.MySQL
1813 cmd.Parameters.AddWithValue("MediaLoop", land.MediaLoop); 1876 cmd.Parameters.AddWithValue("MediaLoop", land.MediaLoop);
1814 cmd.Parameters.AddWithValue("ObscureMusic", land.ObscureMusic); 1877 cmd.Parameters.AddWithValue("ObscureMusic", land.ObscureMusic);
1815 cmd.Parameters.AddWithValue("ObscureMedia", land.ObscureMedia); 1878 cmd.Parameters.AddWithValue("ObscureMedia", land.ObscureMedia);
1879 cmd.Parameters.AddWithValue("SeeAVs", land.SeeAVs ? 1 : 0);
1880 cmd.Parameters.AddWithValue("AnyAVSounds", land.AnyAVSounds ? 1 : 0);
1881 cmd.Parameters.AddWithValue("GroupAVSounds", land.GroupAVSounds ? 1 : 0);
1882
1816 } 1883 }
1817 1884
1818 /// <summary> 1885 /// <summary>
@@ -1919,7 +1986,7 @@ namespace OpenSim.Data.MySQL
1919 cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml()); 1986 cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml());
1920 } 1987 }
1921 1988
1922 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) 1989 public virtual void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
1923 { 1990 {
1924 lock (m_dbLock) 1991 lock (m_dbLock)
1925 { 1992 {
@@ -1963,6 +2030,37 @@ namespace OpenSim.Data.MySQL
1963 } 2030 }
1964 } 2031 }
1965 2032
2033 public UUID[] GetObjectIDs(UUID regionID)
2034 {
2035 List<UUID> uuids = new List<UUID>();
2036
2037 lock (m_dbLock)
2038 {
2039 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
2040 {
2041 dbcon.Open();
2042
2043 using (MySqlCommand cmd = dbcon.CreateCommand())
2044 {
2045 cmd.CommandText = "select UUID from prims where RegionUUID = ?RegionUUID and SceneGroupID = UUID";
2046 cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
2047
2048 using (IDataReader reader = ExecuteReader(cmd))
2049 {
2050 while (reader.Read())
2051 {
2052 UUID id = new UUID(reader["UUID"].ToString());
2053
2054 uuids.Add(id);
2055 }
2056 }
2057 }
2058 }
2059 }
2060
2061 return uuids.ToArray();
2062 }
2063
1966 private void LoadSpawnPoints(RegionSettings rs) 2064 private void LoadSpawnPoints(RegionSettings rs)
1967 { 2065 {
1968 rs.ClearSpawnPoints(); 2066 rs.ClearSpawnPoints();
diff --git a/OpenSim/Data/MySQL/MySQLUserAccountData.cs b/OpenSim/Data/MySQL/MySQLUserAccountData.cs
index e964295..59cfe70 100644
--- a/OpenSim/Data/MySQL/MySQLUserAccountData.cs
+++ b/OpenSim/Data/MySQL/MySQLUserAccountData.cs
@@ -46,17 +46,21 @@ namespace OpenSim.Data.MySQL
46 { 46 {
47 string[] words = query.Split(new char[] {' '}); 47 string[] words = query.Split(new char[] {' '});
48 48
49 bool valid = false;
50
49 for (int i = 0 ; i < words.Length ; i++) 51 for (int i = 0 ; i < words.Length ; i++)
50 { 52 {
51 if (words[i].Length < 3) 53 if (words[i].Length > 2)
52 { 54 valid = true;
53 if (i != words.Length - 1) 55// if (words[i].Length < 3)
54 Array.Copy(words, i + 1, words, i, words.Length - i - 1); 56// {
55 Array.Resize(ref words, words.Length - 1); 57// if (i != words.Length - 1)
56 } 58// Array.Copy(words, i + 1, words, i, words.Length - i - 1);
59// Array.Resize(ref words, words.Length - 1);
60// }
57 } 61 }
58 62
59 if (words.Length == 0) 63 if ((!valid) || words.Length == 0)
60 return new UserAccountData[0]; 64 return new UserAccountData[0];
61 65
62 if (words.Length > 2) 66 if (words.Length > 2)
@@ -66,13 +70,13 @@ namespace OpenSim.Data.MySQL
66 { 70 {
67 if (words.Length == 1) 71 if (words.Length == 1)
68 { 72 {
69 cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search)", m_Realm); 73 cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search) and active=1", m_Realm);
70 cmd.Parameters.AddWithValue("?search", "%" + words[0] + "%"); 74 cmd.Parameters.AddWithValue("?search", "%" + words[0] + "%");
71 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString()); 75 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
72 } 76 }
73 else 77 else
74 { 78 {
75 cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst or LastName like ?searchLast)", m_Realm); 79 cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast) and active=1", m_Realm);
76 cmd.Parameters.AddWithValue("?searchFirst", "%" + words[0] + "%"); 80 cmd.Parameters.AddWithValue("?searchFirst", "%" + words[0] + "%");
77 cmd.Parameters.AddWithValue("?searchLast", "%" + words[1] + "%"); 81 cmd.Parameters.AddWithValue("?searchLast", "%" + words[1] + "%");
78 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString()); 82 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
@@ -81,5 +85,21 @@ namespace OpenSim.Data.MySQL
81 return DoQuery(cmd); 85 return DoQuery(cmd);
82 } 86 }
83 } 87 }
88
89 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
90 {
91 using (MySqlCommand cmd = new MySqlCommand())
92 {
93 if (scopeID != UUID.Zero)
94 {
95 where = "(ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (" + where + ")";
96 cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
97 }
98
99 cmd.CommandText = String.Format("select * from {0} where " + where, m_Realm);
100
101 return DoQuery(cmd);
102 }
103 }
84 } 104 }
85} \ No newline at end of file 105}
diff --git a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs
index b35595d..295e131 100644
--- a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs
+++ b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs
@@ -631,6 +631,8 @@ namespace OpenSim.Data.MySQL
631 { 631 {
632 if(reader.HasRows) 632 if(reader.HasRows)
633 { 633 {
634 m_log.DebugFormat("[PROFILES_DATA]" +
635 ": Getting data for {0}.", props.UserId);
634 reader.Read(); 636 reader.Read();
635 props.WebUrl = (string)reader["profileURL"]; 637 props.WebUrl = (string)reader["profileURL"];
636 UUID.TryParse((string)reader["profileImage"], out props.ImageId); 638 UUID.TryParse((string)reader["profileImage"], out props.ImageId);
@@ -646,6 +648,9 @@ namespace OpenSim.Data.MySQL
646 } 648 }
647 else 649 else
648 { 650 {
651 m_log.DebugFormat("[PROFILES_DATA]" +
652 ": No data for {0}", props.UserId);
653
649 props.WebUrl = string.Empty; 654 props.WebUrl = string.Empty;
650 props.ImageId = UUID.Zero; 655 props.ImageId = UUID.Zero;
651 props.AboutText = string.Empty; 656 props.AboutText = string.Empty;
@@ -894,13 +899,13 @@ namespace OpenSim.Data.MySQL
894 public bool GetUserPreferences(ref UserPreferences pref, ref string result) 899 public bool GetUserPreferences(ref UserPreferences pref, ref string result)
895 { 900 {
896 string query = string.Empty; 901 string query = string.Empty;
897 902
898 query += "SELECT imviaemail,visible,email FROM "; 903 query += "SELECT imviaemail,visible,email FROM ";
899 query += "usersettings WHERE "; 904 query += "usersettings WHERE ";
900 query += "useruuid = ?Id"; 905 query += "useruuid = ?Id";
901 906
902 OSDArray data = new OSDArray(); 907 OSDArray data = new OSDArray();
903 908
904 try 909 try
905 { 910 {
906 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString)) 911 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
@@ -909,10 +914,9 @@ namespace OpenSim.Data.MySQL
909 using (MySqlCommand cmd = new MySqlCommand(query, dbcon)) 914 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
910 { 915 {
911 cmd.Parameters.AddWithValue("?Id", pref.UserId.ToString()); 916 cmd.Parameters.AddWithValue("?Id", pref.UserId.ToString());
912
913 using (MySqlDataReader reader = cmd.ExecuteReader()) 917 using (MySqlDataReader reader = cmd.ExecuteReader())
914 { 918 {
915 if(reader.HasRows) 919 if (reader.HasRows)
916 { 920 {
917 reader.Read(); 921 reader.Read();
918 bool.TryParse((string)reader["imviaemail"], out pref.IMViaEmail); 922 bool.TryParse((string)reader["imviaemail"], out pref.IMViaEmail);
@@ -923,13 +927,13 @@ namespace OpenSim.Data.MySQL
923 { 927 {
924 dbcon.Close(); 928 dbcon.Close();
925 dbcon.Open(); 929 dbcon.Open();
926 930
927 query = "INSERT INTO usersettings VALUES "; 931 query = "INSERT INTO usersettings VALUES ";
928 query += "(?uuid,'false','false', ?Email)"; 932 query += "(?uuid,'false','false', ?Email)";
929 933
930 using (MySqlCommand put = new MySqlCommand(query, dbcon)) 934 using (MySqlCommand put = new MySqlCommand(query, dbcon))
931 { 935 {
932 936
933 put.Parameters.AddWithValue("?Email", pref.EMail); 937 put.Parameters.AddWithValue("?Email", pref.EMail);
934 put.Parameters.AddWithValue("?uuid", pref.UserId.ToString()); 938 put.Parameters.AddWithValue("?uuid", pref.UserId.ToString());
935 939
@@ -949,9 +953,9 @@ namespace OpenSim.Data.MySQL
949 } 953 }
950 return true; 954 return true;
951 } 955 }
952 956
953 public bool UpdateUserPreferences(ref UserPreferences pref, ref string result) 957 public bool UpdateUserPreferences(ref UserPreferences pref, ref string result)
954 { 958 {
955 string query = string.Empty; 959 string query = string.Empty;
956 960
957 query += "UPDATE usersettings SET "; 961 query += "UPDATE usersettings SET ";
@@ -959,7 +963,7 @@ namespace OpenSim.Data.MySQL
959 query += "visible=?Visible, "; 963 query += "visible=?Visible, ";
960 query += "email=?EMail "; 964 query += "email=?EMail ";
961 query += "WHERE useruuid=?uuid"; 965 query += "WHERE useruuid=?uuid";
962 966
963 try 967 try
964 { 968 {
965 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString)) 969 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
diff --git a/OpenSim/Data/MySQL/MySQLXAssetData.cs b/OpenSim/Data/MySQL/MySQLXAssetData.cs
index af7e876..68e1a5a 100644
--- a/OpenSim/Data/MySQL/MySQLXAssetData.cs
+++ b/OpenSim/Data/MySQL/MySQLXAssetData.cs
@@ -500,4 +500,4 @@ namespace OpenSim.Data.MySQL
500 500
501 #endregion 501 #endregion
502 } 502 }
503} \ No newline at end of file 503}
diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
index ac31380..a3d4b5d 100644
--- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
@@ -717,7 +717,7 @@ ALTER TABLE regionsettings ADD COLUMN loaded_creation_datetime int unsigned NOT
717 717
718COMMIT; 718COMMIT;
719 719
720:VERSION 32 720:VERSION 32 #---------------------
721 721
722BEGIN; 722BEGIN;
723CREATE TABLE `regionwindlight` ( 723CREATE TABLE `regionwindlight` (
@@ -948,3 +948,25 @@ ALTER TABLE land CHANGE COLUMN LandFlags LandFlags int unsigned default null;
948 948
949COMMIT; 949COMMIT;
950 950
951:VERSION 51 #---- avination fields
952
953BEGIN;
954
955ALTER TABLE `prims` ADD COLUMN `PassCollisions` tinyint(4) NOT NULL default '0';
956ALTER TABLE `prims` ADD COLUMN `Vehicle` TEXT default NULL;
957ALTER TABLE `regionsettings` ADD COLUMN `block_search` tinyint(4) NOT NULL default '0';
958ALTER TABLE `regionsettings` ADD COLUMN `casino` tinyint(4) NOT NULL default '0';
959ALTER TABLE `land` ADD COLUMN `SeeAVs` tinyint(4) NOT NULL default '1';
960ALTER TABLE `land` ADD COLUMN `AnyAVSounds` tinyint(4) NOT NULL default '1';
961ALTER TABLE `land` ADD COLUMN `GroupAVSounds` tinyint(4) NOT NULL default '1';
962
963COMMIT;
964
965:VERSION 52 #---- STATUS ROTATION axis locks
966
967BEGIN;
968
969ALTER TABLE `prims` ADD COLUMN `RotationAxisLocks` tinyint(4) NOT NULL default '0';
970
971COMMIT;
972
diff --git a/OpenSim/Data/MySQL/Resources/UserAccount.migrations b/OpenSim/Data/MySQL/Resources/UserAccount.migrations
index 84011e6..71f1cc4 100644
--- a/OpenSim/Data/MySQL/Resources/UserAccount.migrations
+++ b/OpenSim/Data/MySQL/Resources/UserAccount.migrations
@@ -44,4 +44,11 @@ ALTER TABLE UserAccounts ADD COLUMN UserTitle varchar(64) NOT NULL DEFAULT '';
44 44
45COMMIT; 45COMMIT;
46 46
47:VERSION 5 # -------------------------
48
49BEGIN;
50
51ALTER TABLE `UserAccounts` ADD `active` INT NOT NULL DEFAULT '1';
52
53COMMIT;
47 54
diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs
index d28cd99..595db2f 100644
--- a/OpenSim/Data/Null/NullRegionData.cs
+++ b/OpenSim/Data/Null/NullRegionData.cs
@@ -134,21 +134,22 @@ namespace OpenSim.Data.Null
134 if (m_useStaticInstance && Instance != this) 134 if (m_useStaticInstance && Instance != this)
135 return Instance.Get(posX, posY, scopeID); 135 return Instance.Get(posX, posY, scopeID);
136 136
137 List<RegionData> ret = new List<RegionData>(); 137 RegionData ret = null;
138 138
139 lock (m_regionData) 139 lock (m_regionData)
140 { 140 {
141 foreach (RegionData r in m_regionData.Values) 141 foreach (RegionData r in m_regionData.Values)
142 { 142 {
143 if (r.posX == posX && r.posY == posY) 143 if (posX >= r.posX && posX < r.posX + r.sizeX
144 ret.Add(r); 144 && posY >= r.posY && posY < r.posY + r.sizeY)
145 {
146 ret = r;
147 break;
148 }
145 } 149 }
146 } 150 }
147 151
148 if (ret.Count > 0) 152 return ret;
149 return ret[0];
150
151 return null;
152 } 153 }
153 154
154 public RegionData Get(UUID regionID, UUID scopeID) 155 public RegionData Get(UUID regionID, UUID scopeID)
@@ -176,8 +177,9 @@ namespace OpenSim.Data.Null
176 { 177 {
177 foreach (RegionData r in m_regionData.Values) 178 foreach (RegionData r in m_regionData.Values)
178 { 179 {
179 if (r.posX >= startX && r.posX <= endX && r.posY >= startY && r.posY <= endY) 180 if (r.posX + r.sizeX > startX && r.posX <= endX
180 ret.Add(r); 181 && r.posY + r.sizeX > startY && r.posY <= endY)
182 ret.Add(r);
181 } 183 }
182 } 184 }
183 185
diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs
index deeaced..339e7f4 100644
--- a/OpenSim/Data/Null/NullSimulationData.cs
+++ b/OpenSim/Data/Null/NullSimulationData.cs
@@ -184,6 +184,11 @@ namespace OpenSim.Data.Null
184 { 184 {
185 } 185 }
186 186
187 public UUID[] GetObjectIDs(UUID regionID)
188 {
189 return new UUID[0];
190 }
191
187 public void SaveExtra(UUID regionID, string name, string value) 192 public void SaveExtra(UUID regionID, string name, string value)
188 { 193 {
189 } 194 }
diff --git a/OpenSim/Data/Null/NullUserAccountData.cs b/OpenSim/Data/Null/NullUserAccountData.cs
index ec54dba..241616b 100644
--- a/OpenSim/Data/Null/NullUserAccountData.cs
+++ b/OpenSim/Data/Null/NullUserAccountData.cs
@@ -193,5 +193,10 @@ namespace OpenSim.Data.Null
193 193
194 return false; 194 return false;
195 } 195 }
196
197 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
198 {
199 return null;
200 }
196 } 201 }
197} 202}
diff --git a/OpenSim/Data/PGSQL/PGSQLAssetData.cs b/OpenSim/Data/PGSQL/PGSQLAssetData.cs
index 5d8b0a2..81adb03 100644
--- a/OpenSim/Data/PGSQL/PGSQLAssetData.cs
+++ b/OpenSim/Data/PGSQL/PGSQLAssetData.cs
@@ -149,7 +149,7 @@ namespace OpenSim.Data.PGSQL
149 /// Create asset in m_database 149 /// Create asset in m_database
150 /// </summary> 150 /// </summary>
151 /// <param name="asset">the asset</param> 151 /// <param name="asset">the asset</param>
152 override public void StoreAsset(AssetBase asset) 152 override public bool StoreAsset(AssetBase asset)
153 { 153 {
154 154
155 string sql = 155 string sql =
@@ -208,6 +208,7 @@ namespace OpenSim.Data.PGSQL
208 m_log.Error("[ASSET DB]: Error storing item :" + e.Message + " sql "+sql); 208 m_log.Error("[ASSET DB]: Error storing item :" + e.Message + " sql "+sql);
209 } 209 }
210 } 210 }
211 return true;
211 } 212 }
212 213
213 214
diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
index 77d87d4..a006c58 100644
--- a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
+++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
@@ -2227,6 +2227,11 @@ namespace OpenSim.Data.PGSQL
2227 } 2227 }
2228 } 2228 }
2229 2229
2230 public UUID[] GetObjectIDs(UUID regionID)
2231 {
2232 return new UUID[0];
2233 }
2234
2230 public void SaveExtra(UUID regionID, string name, string value) 2235 public void SaveExtra(UUID regionID, string name, string value)
2231 { 2236 {
2232 } 2237 }
diff --git a/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs b/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
index 0a68b23..a2b5a2a 100644
--- a/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
+++ b/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
@@ -325,5 +325,10 @@ namespace OpenSim.Data.PGSQL
325 return DoQuery(cmd); 325 return DoQuery(cmd);
326 } 326 }
327 } 327 }
328
329 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
330 {
331 return null;
332 }
328 } 333 }
329} 334}
diff --git a/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations b/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
index a6bd8ca..c1580b2 100644
--- a/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
+++ b/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
@@ -152,4 +152,4 @@ BEGIN;
152 152
153ALTER TABLE usersettings ALTER COLUMN imviaemail SET DATA TYPE boolean USING CASE WHEN false THEN false ELSE true END; 153ALTER TABLE usersettings ALTER COLUMN imviaemail SET DATA TYPE boolean USING CASE WHEN false THEN false ELSE true END;
154 154
155COMMIT; \ No newline at end of file 155COMMIT;
diff --git a/OpenSim/Data/SQLite/Resources/RegionStore.migrations b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
index 901068f..f66be34 100644
--- a/OpenSim/Data/SQLite/Resources/RegionStore.migrations
+++ b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
@@ -612,3 +612,25 @@ ALTER TABLE primshapes ADD COLUMN LastAttachPoint int not null default '0';
612 612
613COMMIT; 613COMMIT;
614 614
615:VERSION 31 #---- avination fields plus a few others
616
617BEGIN;
618
619ALTER TABLE `prims` ADD COLUMN `PassTouches` BOOLEAN NOT NULL DEFAULT FALSE;
620ALTER TABLE `prims` ADD COLUMN `PassCollisions`BOOLEAN NOT NULL DEFAULT FALSE;
621ALTER TABLE `prims` ADD COLUMN `Vehicle` TEXT default NULL;
622ALTER TABLE `regionsettings` ADD COLUMN `block_search` BOOLEAN NOT NULL DEFAULT FALSE;;
623ALTER TABLE `regionsettings` ADD COLUMN `casino` BOOLEAN NOT NULL DEFAULT FALSE;;
624ALTER TABLE `land` ADD COLUMN `SeeAVs` BOOLEAN NOT NULL DEFAULT TRUE;
625ALTER TABLE `land` ADD COLUMN `AnyAVSounds` BOOLEAN NOT NULL DEFAULT TRUE;
626ALTER TABLE `land` ADD COLUMN `GroupAVSounds` BOOLEAN NOT NULL DEFAULT TRUE;
627
628COMMIT;
629
630:VERSION 32 #---- Rotation axis locks
631
632BEGIN;
633
634ALTER TABLE prims ADD COLUMN `RotationAxisLocks` tinyint(4) NOT NULL default '0';
635
636COMMIT;
diff --git a/OpenSim/Data/SQLite/Resources/UserAccount.migrations b/OpenSim/Data/SQLite/Resources/UserAccount.migrations
index 854fe69..f37a222 100644
--- a/OpenSim/Data/SQLite/Resources/UserAccount.migrations
+++ b/OpenSim/Data/SQLite/Resources/UserAccount.migrations
@@ -25,3 +25,11 @@ BEGIN TRANSACTION;
25INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT `UUID` AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, username AS FirstName, surname AS LastName, '' as Email, '' AS ServiceURLs, created as Created FROM users; 25INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT `UUID` AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, username AS FirstName, surname AS LastName, '' as Email, '' AS ServiceURLs, created as Created FROM users;
26 26
27COMMIT; 27COMMIT;
28
29:VERSION 3 # -------------------------
30
31BEGIN;
32
33ALTER TABLE `UserAccounts` ADD `active` BOOLEAN NOT NULL DEFAULT TRUE;
34
35COMMIT; \ No newline at end of file
diff --git a/OpenSim/Data/SQLite/Resources/UserProfiles.migrations b/OpenSim/Data/SQLite/Resources/UserProfiles.migrations
index 86434e8..207dde0 100644
--- a/OpenSim/Data/SQLite/Resources/UserProfiles.migrations
+++ b/OpenSim/Data/SQLite/Resources/UserProfiles.migrations
@@ -99,4 +99,4 @@ CREATE TABLE IF NOT EXISTS usersettings (
99 email varchar(254) NOT NULL, 99 email varchar(254) NOT NULL,
100 PRIMARY KEY (useruuid) 100 PRIMARY KEY (useruuid)
101) 101)
102commit; \ No newline at end of file 102commit;
diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs
index f0dda64..9c2bd2e 100644
--- a/OpenSim/Data/SQLite/SQLiteAssetData.cs
+++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs
@@ -131,7 +131,7 @@ namespace OpenSim.Data.SQLite
131 /// Create an asset 131 /// Create an asset
132 /// </summary> 132 /// </summary>
133 /// <param name="asset">Asset Base</param> 133 /// <param name="asset">Asset Base</param>
134 override public void StoreAsset(AssetBase asset) 134 override public bool StoreAsset(AssetBase asset)
135 { 135 {
136 string assetName = asset.Name; 136 string assetName = asset.Name;
137 if (asset.Name.Length > AssetBase.MAX_ASSET_NAME) 137 if (asset.Name.Length > AssetBase.MAX_ASSET_NAME)
@@ -171,6 +171,7 @@ namespace OpenSim.Data.SQLite
171 cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); 171 cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data));
172 172
173 cmd.ExecuteNonQuery(); 173 cmd.ExecuteNonQuery();
174 return true;
174 } 175 }
175 } 176 }
176 } 177 }
@@ -191,6 +192,7 @@ namespace OpenSim.Data.SQLite
191 cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); 192 cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data));
192 193
193 cmd.ExecuteNonQuery(); 194 cmd.ExecuteNonQuery();
195 return true;
194 } 196 }
195 } 197 }
196 } 198 }
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 6ed3d40..d7b3bbe 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -1246,6 +1246,7 @@ namespace OpenSim.Data.SQLite
1246 createCol(prims, "Restitution", typeof(Double)); 1246 createCol(prims, "Restitution", typeof(Double));
1247 1247
1248 createCol(prims, "KeyframeMotion", typeof(Byte[])); 1248 createCol(prims, "KeyframeMotion", typeof(Byte[]));
1249
1249 // Add in contraints 1250 // Add in contraints
1250 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; 1251 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
1251 1252
@@ -1760,7 +1761,18 @@ namespace OpenSim.Data.SQLite
1760 { 1761 {
1761 prim.KeyframeMotion = null; 1762 prim.KeyframeMotion = null;
1762 } 1763 }
1763 1764
1765 prim.PassCollisions = Convert.ToBoolean(row["PassCollisions"]);
1766 prim.PassTouches = Convert.ToBoolean(row["PassTouches"]);
1767 prim.RotationAxisLocks = Convert.ToByte(row["RotationAxisLocks"]);
1768
1769 SOPVehicle vehicle = null;
1770 if (!(row["Vehicle"] is DBNull) && row["Vehicle"].ToString() != String.Empty)
1771 {
1772 vehicle = SOPVehicle.FromXml2(row["Vehicle"].ToString());
1773 if (vehicle != null)
1774 prim.VehicleParams = vehicle;
1775 }
1764 return prim; 1776 return prim;
1765 } 1777 }
1766 1778
@@ -1845,6 +1857,10 @@ namespace OpenSim.Data.SQLite
1845 newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]); 1857 newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]);
1846 newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]); 1858 newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]);
1847 newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]); 1859 newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]);
1860 newData.SeeAVs = Convert.ToBoolean(row["SeeAVs"]);
1861 newData.AnyAVSounds = Convert.ToBoolean(row["AnyAVSounds"]);
1862 newData.GroupAVSounds = Convert.ToBoolean(row["GroupAVSounds"]);
1863
1848 try 1864 try
1849 { 1865 {
1850 newData.UserLocation = 1866 newData.UserLocation =
@@ -1918,7 +1934,8 @@ namespace OpenSim.Data.SQLite
1918 newSettings.TerrainImageID = new UUID((String)row["map_tile_ID"]); 1934 newSettings.TerrainImageID = new UUID((String)row["map_tile_ID"]);
1919 newSettings.TelehubObject = new UUID((String)row["TelehubObject"]); 1935 newSettings.TelehubObject = new UUID((String)row["TelehubObject"]);
1920 newSettings.ParcelImageID = new UUID((String)row["parcel_tile_ID"]); 1936 newSettings.ParcelImageID = new UUID((String)row["parcel_tile_ID"]);
1921 1937 newSettings.GodBlockSearch = Convert.ToBoolean(row["block_search"]);
1938 newSettings.Casino = Convert.ToBoolean(row["casino"]);
1922 return newSettings; 1939 return newSettings;
1923 } 1940 }
1924 1941
@@ -2013,6 +2030,7 @@ namespace OpenSim.Data.SQLite
2013 return entry; 2030 return entry;
2014 } 2031 }
2015 2032
2033
2016 /// <summary> 2034 /// <summary>
2017 /// 2035 ///
2018 /// </summary> 2036 /// </summary>
@@ -2137,7 +2155,6 @@ namespace OpenSim.Data.SQLite
2137 // click action 2155 // click action
2138 row["ClickAction"] = prim.ClickAction; 2156 row["ClickAction"] = prim.ClickAction;
2139 2157
2140 row["SalePrice"] = prim.SalePrice;
2141 row["Material"] = prim.Material; 2158 row["Material"] = prim.Material;
2142 2159
2143 row["CollisionSound"] = prim.CollisionSound.ToString(); 2160 row["CollisionSound"] = prim.CollisionSound.ToString();
@@ -2168,8 +2185,16 @@ namespace OpenSim.Data.SQLite
2168 row["KeyframeMotion"] = prim.KeyframeMotion.Serialize(); 2185 row["KeyframeMotion"] = prim.KeyframeMotion.Serialize();
2169 else 2186 else
2170 row["KeyframeMotion"] = new Byte[0]; 2187 row["KeyframeMotion"] = new Byte[0];
2171 2188
2172 2189 row["PassTouches"] = prim.PassTouches;
2190 row["PassCollisions"] = prim.PassCollisions;
2191 row["RotationAxisLocks"] = prim.RotationAxisLocks;
2192
2193 if (prim.VehicleParams != null)
2194 row["Vehicle"] = prim.VehicleParams.ToXml2();
2195 else
2196 row["Vehicle"] = String.Empty;
2197
2173 } 2198 }
2174 2199
2175 /// <summary> 2200 /// <summary>
@@ -2253,6 +2278,10 @@ namespace OpenSim.Data.SQLite
2253 row["MediaLoop"] = land.MediaLoop; 2278 row["MediaLoop"] = land.MediaLoop;
2254 row["ObscureMusic"] = land.ObscureMusic; 2279 row["ObscureMusic"] = land.ObscureMusic;
2255 row["ObscureMedia"] = land.ObscureMedia; 2280 row["ObscureMedia"] = land.ObscureMedia;
2281 row["SeeAVs"] = land.SeeAVs;
2282 row["AnyAVSounds"] = land.AnyAVSounds;
2283 row["GroupAVSounds"] = land.GroupAVSounds;
2284
2256 } 2285 }
2257 2286
2258 /// <summary> 2287 /// <summary>
@@ -2311,6 +2340,8 @@ namespace OpenSim.Data.SQLite
2311 row["map_tile_ID"] = settings.TerrainImageID.ToString(); 2340 row["map_tile_ID"] = settings.TerrainImageID.ToString();
2312 row["TelehubObject"] = settings.TelehubObject.ToString(); 2341 row["TelehubObject"] = settings.TelehubObject.ToString();
2313 row["parcel_tile_ID"] = settings.ParcelImageID.ToString(); 2342 row["parcel_tile_ID"] = settings.ParcelImageID.ToString();
2343 row["block_search"] = settings.GodBlockSearch;
2344 row["casino"] = settings.Casino;
2314 } 2345 }
2315 2346
2316 /// <summary> 2347 /// <summary>
@@ -2944,6 +2975,11 @@ namespace OpenSim.Data.SQLite
2944 } 2975 }
2945 } 2976 }
2946 2977
2978 public UUID[] GetObjectIDs(UUID regionID)
2979 {
2980 return new UUID[0];
2981 }
2982
2947 public void SaveExtra(UUID regionID, string name, string value) 2983 public void SaveExtra(UUID regionID, string name, string value)
2948 { 2984 {
2949 } 2985 }
diff --git a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
index f98d376..91d62ce 100644
--- a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
+++ b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
@@ -82,5 +82,10 @@ namespace OpenSim.Data.SQLite
82 return DoQuery(cmd); 82 return DoQuery(cmd);
83 } 83 }
84 } 84 }
85
86 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
87 {
88 return null;
89 }
85 } 90 }
86} 91}
diff --git a/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs b/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs
index cd3e8b6..2dfdba3 100644
--- a/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs
+++ b/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs
@@ -741,6 +741,7 @@ namespace OpenSim.Data.SQLite
741 return true; 741 return true;
742 } 742 }
743 743
744
744 public bool UpdateUserPreferences(ref UserPreferences pref, ref string result) 745 public bool UpdateUserPreferences(ref UserPreferences pref, ref string result)
745 { 746 {
746 string query = string.Empty; 747 string query = string.Empty;
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs
index 0d053e4..4529944 100644
--- a/OpenSim/Framework/AgentCircuitData.cs
+++ b/OpenSim/Framework/AgentCircuitData.cs
@@ -184,7 +184,7 @@ namespace OpenSim.Framework
184 /// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json 184 /// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json
185 /// </summary> 185 /// </summary>
186 /// <returns>map of the agent circuit data</returns> 186 /// <returns>map of the agent circuit data</returns>
187 public OSDMap PackAgentCircuitData() 187 public OSDMap PackAgentCircuitData(EntityTransferContext ctx)
188 { 188 {
189 OSDMap args = new OSDMap(); 189 OSDMap args = new OSDMap();
190 args["agent_id"] = OSD.FromUUID(AgentID); 190 args["agent_id"] = OSD.FromUUID(AgentID);
@@ -224,7 +224,7 @@ namespace OpenSim.Framework
224 { 224 {
225 args["appearance_serial"] = OSD.FromInteger(Appearance.Serial); 225 args["appearance_serial"] = OSD.FromInteger(Appearance.Serial);
226 226
227 OSDMap appmap = Appearance.Pack(); 227 OSDMap appmap = Appearance.Pack(ctx);
228 args["packed_appearance"] = appmap; 228 args["packed_appearance"] = appmap;
229 } 229 }
230 230
diff --git a/OpenSim/Framework/AnimationSet.cs b/OpenSim/Framework/AnimationSet.cs
new file mode 100644
index 0000000..6c5b15c
--- /dev/null
+++ b/OpenSim/Framework/AnimationSet.cs
@@ -0,0 +1,168 @@
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 delegate bool AnimationSetValidator(UUID animID);
35
36 public class AnimationSet
37 {
38 private bool m_parseError = false;
39
40 public const uint createBasePermitions = (uint)(PermissionMask.All); // no export ?
41 public const uint createNextPermitions = (uint)(PermissionMask.Copy | PermissionMask.Modify);
42
43 public const uint allowedBasePermitions = (uint)(PermissionMask.Copy | PermissionMask.Modify);
44 public const uint allowedNextPermitions = 0;
45
46 public static void setCreateItemPermitions(InventoryItemBase it)
47 {
48 if (it == null)
49 return;
50
51 it.BasePermissions = createBasePermitions;
52 it.CurrentPermissions = createBasePermitions;
53 // it.GroupPermissions &= allowedPermitions;
54 it.NextPermissions = createNextPermitions;
55 // it.EveryOnePermissions &= allowedPermitions;
56 it.GroupPermissions = 0;
57 it.EveryOnePermissions = 0;
58 }
59
60 public static void enforceItemPermitions(InventoryItemBase it, bool IsCreator)
61 {
62 if (it == null)
63 return;
64
65 uint bp;
66 uint np;
67
68 if (IsCreator)
69 {
70 bp = createBasePermitions;
71 np = createNextPermitions;
72 }
73 else
74 {
75 bp = allowedBasePermitions;
76 np = allowedNextPermitions;
77 }
78
79 it.BasePermissions &= bp;
80 it.CurrentPermissions &= bp;
81 // it.GroupPermissions &= allowedPermitions;
82 it.NextPermissions &= np;
83 // it.EveryOnePermissions &= allowedPermitions;
84 it.GroupPermissions = 0;
85 it.EveryOnePermissions = 0;
86 }
87
88 public int AnimationCount { get; private set; }
89 private Dictionary<string, KeyValuePair<string, UUID>> m_animations = new Dictionary<string, KeyValuePair<string, UUID>>();
90
91 public UUID GetAnimation(string index)
92 {
93 KeyValuePair<string, UUID> val;
94 if (m_animations.TryGetValue(index, out val))
95 return val.Value;
96
97 return UUID.Zero;
98 }
99
100 public string GetAnimationName(string index)
101 {
102 KeyValuePair<string, UUID> val;
103 if (m_animations.TryGetValue(index, out val))
104 return val.Key;
105
106 return String.Empty;
107 }
108
109 public void SetAnimation(string index, string name, UUID anim)
110 {
111 if (anim == UUID.Zero)
112 {
113 m_animations.Remove(index);
114 return;
115 }
116
117 m_animations[index] = new KeyValuePair<string, UUID>(name, anim);
118 }
119
120 public AnimationSet(Byte[] data)
121 {
122 string assetData = System.Text.Encoding.ASCII.GetString(data);
123 Console.WriteLine("--------------------");
124 Console.WriteLine("AnimationSet length {0} bytes", assetData.Length);
125 Console.WriteLine(assetData);
126 Console.WriteLine("--------------------");
127 }
128
129 public Byte[] ToBytes()
130 {
131 // If there was an error parsing the input, we give back an
132 // empty set rather than the original data.
133 if (m_parseError)
134 {
135 string dummy = "version 1\ncount 0\n";
136 return System.Text.Encoding.ASCII.GetBytes(dummy);
137 }
138
139 string assetData = String.Format("version 1\ncount {0}\n", m_animations.Count);
140 foreach (KeyValuePair<string, KeyValuePair<string, UUID>> kvp in m_animations)
141 assetData += String.Format("{0} {1} {2}\n", kvp.Key, kvp.Value.Value.ToString(), kvp.Value.Key);
142 return System.Text.Encoding.ASCII.GetBytes(assetData);
143 }
144
145 public bool Validate(AnimationSetValidator val)
146 {
147 if (m_parseError)
148 return false;
149
150 List<string> badAnims = new List<string>();
151
152 bool allOk = true;
153 foreach (KeyValuePair<string, KeyValuePair<string, UUID>> kvp in m_animations)
154 {
155 if (!val(kvp.Value.Value))
156 {
157 allOk = false;
158 badAnims.Add(kvp.Key);
159 }
160 }
161
162 foreach (string idx in badAnims)
163 m_animations.Remove(idx);
164
165 return allOk;
166 }
167 }
168}
diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs
index 2f04d2e..33be612 100644
--- a/OpenSim/Framework/AssetBase.cs
+++ b/OpenSim/Framework/AssetBase.cs
@@ -63,6 +63,8 @@ namespace OpenSim.Framework
63 /// </summary> 63 /// </summary>
64 private AssetMetadata m_metadata; 64 private AssetMetadata m_metadata;
65 65
66 private int m_uploadAttempts;
67
66 // This is needed for .NET serialization!!! 68 // This is needed for .NET serialization!!!
67 // Do NOT "Optimize" away! 69 // Do NOT "Optimize" away!
68 public AssetBase() 70 public AssetBase()
@@ -148,7 +150,8 @@ namespace OpenSim.Framework
148 Type == (sbyte)AssetType.Folder || 150 Type == (sbyte)AssetType.Folder ||
149 Type == (sbyte)AssetType.ImageJPEG || 151 Type == (sbyte)AssetType.ImageJPEG ||
150 Type == (sbyte)AssetType.ImageTGA || 152 Type == (sbyte)AssetType.ImageTGA ||
151 Type == (sbyte)AssetType.LSLBytecode); 153 Type == (sbyte)AssetType.Mesh ||
154 Type == (sbyte) AssetType.LSLBytecode);
152 } 155 }
153 } 156 }
154 157
@@ -197,6 +200,12 @@ namespace OpenSim.Framework
197 set { m_metadata.Type = value; } 200 set { m_metadata.Type = value; }
198 } 201 }
199 202
203 public int UploadAttempts
204 {
205 get { return m_uploadAttempts; }
206 set { m_uploadAttempts = value; }
207 }
208
200 /// <summary> 209 /// <summary>
201 /// Is this a region only asset, or does this exist on the asset server also 210 /// Is this a region only asset, or does this exist on the asset server also
202 /// </summary> 211 /// </summary>
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index e1725a9..79a66ab 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -53,7 +53,11 @@ namespace OpenSim.Framework
53 // should be only used as initial default value ( V1 viewers ) 53 // should be only used as initial default value ( V1 viewers )
54 public readonly static int VISUALPARAM_COUNT = 218; 54 public readonly static int VISUALPARAM_COUNT = 218;
55 55
56 public readonly static int TEXTURE_COUNT = 21; 56// public readonly static int TEXTURE_COUNT = 21
57 // 21 bad, make it be updated as libovm gets update
58 // also keeping in sync with it
59 public readonly static int TEXTURE_COUNT = Primitive.TextureEntry.MAX_FACES;
60
57 public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 61 public readonly static byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
58 62
59 protected int m_serial = 0; 63 protected int m_serial = 0;
@@ -179,11 +183,16 @@ namespace OpenSim.Framework
179 m_attachments = new Dictionary<int, List<AvatarAttachment>>(); 183 m_attachments = new Dictionary<int, List<AvatarAttachment>>();
180 } 184 }
181 185
182 public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true) 186 public AvatarAppearance(AvatarAppearance appearance): this(appearance, true,true)
183 { 187 {
184 } 188 }
185 189
186 public AvatarAppearance(AvatarAppearance appearance, bool copyWearables) 190 public AvatarAppearance(AvatarAppearance appearance, bool copyWearables)
191 : this(appearance, copyWearables, true)
192 {
193 }
194
195 public AvatarAppearance(AvatarAppearance appearance, bool copyWearables, bool copyBaked)
187 { 196 {
188// m_log.WarnFormat("[AVATAR APPEARANCE] create from an existing appearance"); 197// m_log.WarnFormat("[AVATAR APPEARANCE] create from an existing appearance");
189 198
@@ -202,21 +211,29 @@ namespace OpenSim.Framework
202 211
203 m_serial = appearance.Serial; 212 m_serial = appearance.Serial;
204 213
205 m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES];
206 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
207 m_wearables[i] = new AvatarWearable();
208
209 if (copyWearables && (appearance.Wearables != null)) 214 if (copyWearables && (appearance.Wearables != null))
210 { 215 {
211 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 216 m_wearables = new AvatarWearable[appearance.Wearables.Length];
212 SetWearable(i,appearance.Wearables[i]); 217 for (int i = 0; i < appearance.Wearables.Length; i++)
218 {
219 m_wearables[i] = new AvatarWearable();
220 AvatarWearable wearable = appearance.Wearables[i];
221 for (int j = 0; j < wearable.Count; j++)
222 m_wearables[i].Add(wearable[j].ItemID, wearable[j].AssetID);
223 }
213 } 224 }
225 else
226 ClearWearables();
214 227
215 m_texture = null; 228 m_texture = null;
216 if (appearance.Texture != null) 229 if (appearance.Texture != null)
217 { 230 {
218 byte[] tbytes = appearance.Texture.GetBytes(); 231 byte[] tbytes = appearance.Texture.GetBytes();
219 m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length); 232 m_texture = new Primitive.TextureEntry(tbytes,0,tbytes.Length);
233 if (copyBaked && appearance.m_cacheitems != null)
234 m_cacheitems = (WearableCacheItem[])appearance.m_cacheitems.Clone();
235 else
236 m_cacheitems = null;
220 } 237 }
221 238
222 m_visualparams = null; 239 m_visualparams = null;
@@ -234,9 +251,17 @@ namespace OpenSim.Framework
234 251
235 public void GetAssetsFrom(AvatarAppearance app) 252 public void GetAssetsFrom(AvatarAppearance app)
236 { 253 {
237 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 254 int len = m_wearables.Length;
255 if(len > app.m_wearables.Length)
256 len = app.m_wearables.Length;
257
258 for (int i = 0; i < len; i++)
238 { 259 {
239 for (int j = 0; j < m_wearables[i].Count; j++) 260 int count = m_wearables[i].Count;
261 if(count > app.m_wearables[i].Count)
262 count = app.m_wearables[i].Count;
263
264 for (int j = 0; j < count; j++)
240 { 265 {
241 UUID itemID = m_wearables[i][j].ItemID; 266 UUID itemID = m_wearables[i][j].ItemID;
242 UUID assetID = app.Wearables[i].GetAsset(itemID); 267 UUID assetID = app.Wearables[i].GetAsset(itemID);
@@ -249,8 +274,8 @@ namespace OpenSim.Framework
249 274
250 public void ClearWearables() 275 public void ClearWearables()
251 { 276 {
252 m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES]; 277 m_wearables = new AvatarWearable[AvatarWearable.LEGACY_VERSION_MAX_WEARABLES];
253 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 278 for (int i = 0; i < AvatarWearable.LEGACY_VERSION_MAX_WEARABLES; i++)
254 m_wearables[i] = new AvatarWearable(); 279 m_wearables[i] = new AvatarWearable();
255 } 280 }
256 281
@@ -457,11 +482,22 @@ namespace OpenSim.Framework
457// DEBUG ON 482// DEBUG ON
458// m_log.WarnFormat("[AVATARAPPEARANCE] set wearable {0} --> {1}:{2}",wearableId,wearable.ItemID,wearable.AssetID); 483// m_log.WarnFormat("[AVATARAPPEARANCE] set wearable {0} --> {1}:{2}",wearableId,wearable.ItemID,wearable.AssetID);
459// DEBUG OFF 484// DEBUG OFF
485 if (wearableId >= m_wearables.Length)
486 {
487 int currentLength = m_wearables.Length;
488 Array.Resize(ref m_wearables, wearableId + 1);
489 for (int i = currentLength ; i < m_wearables.Length ; i++)
490 m_wearables[i] = new AvatarWearable();
491 }
460 m_wearables[wearableId].Clear(); 492 m_wearables[wearableId].Clear();
493<<<<<<< HEAD
494 for (int i = 0; i < wearable.Count; i++)
495=======
461 int count = wearable.Count; 496 int count = wearable.Count;
462 if (count > AvatarWearable.MAX_WEARABLES) 497 if (count > AvatarWearable.MAX_WEARABLES)
463 count = AvatarWearable.MAX_WEARABLES; 498 count = AvatarWearable.MAX_WEARABLES;
464 for (int i = 0; i < count; i++) 499 for (int i = 0; i < count; i++)
500>>>>>>> master
465 m_wearables[wearableId].Add(wearable[i].ItemID, wearable[i].AssetID); 501 m_wearables[wearableId].Add(wearable[i].ItemID, wearable[i].AssetID);
466 } 502 }
467 503
@@ -701,7 +737,7 @@ namespace OpenSim.Framework
701 /// <summary> 737 /// <summary>
702 /// Create an OSDMap from the appearance data 738 /// Create an OSDMap from the appearance data
703 /// </summary> 739 /// </summary>
704 public OSDMap Pack() 740 public OSDMap Pack(EntityTransferContext ctx)
705 { 741 {
706 OSDMap data = new OSDMap(); 742 OSDMap data = new OSDMap();
707 743
@@ -709,9 +745,22 @@ namespace OpenSim.Framework
709 data["height"] = OSD.FromReal(m_avatarHeight); 745 data["height"] = OSD.FromReal(m_avatarHeight);
710 746
711 // Wearables 747 // Wearables
712 OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES); 748 //
713 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 749 // This will send as many or as few wearables as we have, unless a count
714 wears.Add(m_wearables[i].Pack()); 750 // is given. Used for legacy (pre 0.4) versions.
751 int count = ctx.WearablesCount;
752 if (ctx.WearablesCount == -1)
753 count = m_wearables.Length;
754 OSDArray wears = new OSDArray(count);
755 for (int i = 0; i < count; i++)
756 {
757 AvatarWearable dummyWearable = new AvatarWearable();
758
759 if (i < m_wearables.Length)
760 wears.Add(m_wearables[i].Pack());
761 else
762 wears.Add(dummyWearable.Pack());
763 }
715 data["wearables"] = wears; 764 data["wearables"] = wears;
716 765
717 // Avatar Textures 766 // Avatar Textures
@@ -725,6 +774,13 @@ namespace OpenSim.Framework
725 } 774 }
726 data["textures"] = textures; 775 data["textures"] = textures;
727 776
777 if (m_cacheitems != null)
778 {
779 OSDArray baked = WearableCacheItem.BakedToOSD(m_cacheitems);
780 if (baked != null)
781 data["bakedcache"] = baked;
782 }
783
728 // Visual Parameters 784 // Visual Parameters
729 OSDBinary visualparams = new OSDBinary(m_visualparams); 785 OSDBinary visualparams = new OSDBinary(m_visualparams);
730 data["visualparams"] = visualparams; 786 data["visualparams"] = visualparams;
@@ -760,9 +816,11 @@ namespace OpenSim.Framework
760 if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array) 816 if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array)
761 { 817 {
762 OSDArray wears = (OSDArray)(data["wearables"]); 818 OSDArray wears = (OSDArray)(data["wearables"]);
819
763 int count = wears.Count; 820 int count = wears.Count;
764 if (count > AvatarWearable.MAX_WEARABLES) 821
765 count = AvatarWearable.MAX_WEARABLES; 822 m_wearables = new AvatarWearable[count];
823
766 for (int i = 0; i < count; i++) 824 for (int i = 0; i < count; i++)
767 m_wearables[i] = new AvatarWearable((OSDArray)wears[i]); 825 m_wearables[i] = new AvatarWearable((OSDArray)wears[i]);
768 } 826 }
@@ -789,6 +847,12 @@ namespace OpenSim.Framework
789 m_log.Warn("[AVATAR APPEARANCE]: failed to unpack textures"); 847 m_log.Warn("[AVATAR APPEARANCE]: failed to unpack textures");
790 } 848 }
791 849
850 if ((data != null) && (data["bakedcache"] != null) && (data["bakedcache"]).Type == OSDType.Array)
851 {
852 OSDArray bakedOSDArray = (OSDArray)(data["bakedcache"]);
853 m_cacheitems = WearableCacheItem.BakedFromOSD(bakedOSDArray);
854 }
855
792 // Visual Parameters 856 // Visual Parameters
793 SetDefaultParams(); 857 SetDefaultParams();
794 if ((data != null) && (data["visualparams"] != null)) 858 if ((data != null) && (data["visualparams"] != null))
@@ -1638,7 +1702,12 @@ namespace OpenSim.Framework
1638 BREAST_PHYSICS_LEFTRIGHT_MAX_EFFECT = 247, 1702 BREAST_PHYSICS_LEFTRIGHT_MAX_EFFECT = 247,
1639 BREAST_PHYSICS_LEFTRIGHT_SPRING= 248, 1703 BREAST_PHYSICS_LEFTRIGHT_SPRING= 248,
1640 BREAST_PHYSICS_LEFTRIGHT_GAIN = 249, 1704 BREAST_PHYSICS_LEFTRIGHT_GAIN = 249,
1641 BREAST_PHYSICS_LEFTRIGHT_DAMPING = 250 1705 BREAST_PHYSICS_LEFTRIGHT_DAMPING = 250,
1706
1707 // Ubit: 07/96/2013 new parameters
1708 _APPEARANCEMESSAGE_VERSION = 251, //ID 11000
1709
1710 SHAPE_HOVER = 252, //ID 11001
1642 } 1711 }
1643 #endregion 1712 #endregion
1644 } 1713 }
diff --git a/OpenSim/Framework/AvatarWearable.cs b/OpenSim/Framework/AvatarWearable.cs
index 8e27596..80ed77f 100644
--- a/OpenSim/Framework/AvatarWearable.cs
+++ b/OpenSim/Framework/AvatarWearable.cs
@@ -62,10 +62,16 @@ namespace OpenSim.Framework
62 public static readonly int UNDERSHIRT = 10; 62 public static readonly int UNDERSHIRT = 10;
63 public static readonly int UNDERPANTS = 11; 63 public static readonly int UNDERPANTS = 11;
64 public static readonly int SKIRT = 12; 64 public static readonly int SKIRT = 12;
65
66 public static readonly int MAX_BASICWEARABLES = 13;
67
65 public static readonly int ALPHA = 13; 68 public static readonly int ALPHA = 13;
66 public static readonly int TATTOO = 14; 69 public static readonly int TATTOO = 14;
67 70
68 public static readonly int MAX_WEARABLES = 15; 71 public static readonly int LEGACY_VERSION_MAX_WEARABLES = 15;
72// public static readonly int PHYSICS = 15;
73// public static int MAX_WEARABLES = 16;
74
69 75
70 public static readonly UUID DEFAULT_BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9"); 76 public static readonly UUID DEFAULT_BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9");
71 public static readonly UUID DEFAULT_BODY_ASSET = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); 77 public static readonly UUID DEFAULT_BODY_ASSET = new UUID("66c41e39-38f9-f75a-024e-585989bfab73");
@@ -219,8 +225,9 @@ namespace OpenSim.Framework
219 { 225 {
220 get 226 get
221 { 227 {
222 AvatarWearable[] defaultWearables = new AvatarWearable[MAX_WEARABLES]; //should be 15 of these 228 // We use the legacy count here because this is just a fallback anyway
223 for (int i = 0; i < MAX_WEARABLES; i++) 229 AvatarWearable[] defaultWearables = new AvatarWearable[LEGACY_VERSION_MAX_WEARABLES];
230 for (int i = 0; i < LEGACY_VERSION_MAX_WEARABLES; i++)
224 { 231 {
225 defaultWearables[i] = new AvatarWearable(); 232 defaultWearables[i] = new AvatarWearable();
226 } 233 }
@@ -242,10 +249,13 @@ namespace OpenSim.Framework
242 249
243// // Alpha 250// // Alpha
244// defaultWearables[ALPHA].Add(DEFAULT_ALPHA_ITEM, DEFAULT_ALPHA_ASSET); 251// defaultWearables[ALPHA].Add(DEFAULT_ALPHA_ITEM, DEFAULT_ALPHA_ASSET);
245 252
246// // Tattoo 253 // // Tattoo
247// defaultWearables[TATTOO].Add(DEFAULT_TATTOO_ITEM, DEFAULT_TATTOO_ASSET); 254 // defaultWearables[TATTOO].Add(DEFAULT_TATTOO_ITEM, DEFAULT_TATTOO_ASSET);
248 255
256 // // Physics
257 // defaultWearables[PHYSICS].Add(DEFAULT_TATTOO_ITEM, DEFAULT_TATTOO_ASSET);
258
249 return defaultWearables; 259 return defaultWearables;
250 } 260 }
251 } 261 }
diff --git a/OpenSim/Framework/BlockingQueue.cs b/OpenSim/Framework/BlockingQueue.cs
index d11ad11..daf99a8 100644
--- a/OpenSim/Framework/BlockingQueue.cs
+++ b/OpenSim/Framework/BlockingQueue.cs
@@ -76,10 +76,9 @@ namespace OpenSim.Framework
76 { 76 {
77 lock (m_queueSync) 77 lock (m_queueSync)
78 { 78 {
79 bool success = true; 79 if (m_queue.Count < 1 && m_pqueue.Count < 1)
80 while (m_queue.Count < 1 && m_pqueue.Count < 1 && success)
81 { 80 {
82 success = Monitor.Wait(m_queueSync, msTimeout); 81 Monitor.Wait(m_queueSync, msTimeout);
83 } 82 }
84 83
85 if (m_pqueue.Count > 0) 84 if (m_pqueue.Count > 0)
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs
index 2a8e67d..72c2c34 100644
--- a/OpenSim/Framework/ChildAgentDataUpdate.cs
+++ b/OpenSim/Framework/ChildAgentDataUpdate.cs
@@ -61,8 +61,8 @@ namespace OpenSim.Framework
61 { 61 {
62 UUID AgentID { get; set; } 62 UUID AgentID { get; set; }
63 63
64 OSDMap Pack(); 64 OSDMap Pack(EntityTransferContext ctx);
65 void Unpack(OSDMap map, IScene scene); 65 void Unpack(OSDMap map, IScene scene, EntityTransferContext ctx);
66 } 66 }
67 67
68 /// <summary> 68 /// <summary>
@@ -94,8 +94,9 @@ namespace OpenSim.Framework
94 // This probably shouldn't be here 94 // This probably shouldn't be here
95 public byte[] Throttles; 95 public byte[] Throttles;
96 96
97 public Dictionary<ulong, string> ChildrenCapSeeds = null;
97 98
98 public OSDMap Pack() 99 public OSDMap Pack(EntityTransferContext ctx)
99 { 100 {
100 OSDMap args = new OSDMap(); 101 OSDMap args = new OSDMap();
101 args["message_type"] = OSD.FromString("AgentPosition"); 102 args["message_type"] = OSD.FromString("AgentPosition");
@@ -119,10 +120,23 @@ namespace OpenSim.Framework
119 if ((Throttles != null) && (Throttles.Length > 0)) 120 if ((Throttles != null) && (Throttles.Length > 0))
120 args["throttles"] = OSD.FromBinary(Throttles); 121 args["throttles"] = OSD.FromBinary(Throttles);
121 122
123 if (ChildrenCapSeeds != null && ChildrenCapSeeds.Count > 0)
124 {
125 OSDArray childrenSeeds = new OSDArray(ChildrenCapSeeds.Count);
126 foreach (KeyValuePair<ulong, string> kvp in ChildrenCapSeeds)
127 {
128 OSDMap pair = new OSDMap();
129 pair["handle"] = OSD.FromString(kvp.Key.ToString());
130 pair["seed"] = OSD.FromString(kvp.Value);
131 childrenSeeds.Add(pair);
132 }
133 args["children_seeds"] = childrenSeeds;
134 }
135
122 return args; 136 return args;
123 } 137 }
124 138
125 public void Unpack(OSDMap args, IScene scene) 139 public void Unpack(OSDMap args, IScene scene, EntityTransferContext ctx)
126 { 140 {
127 if (args.ContainsKey("region_handle")) 141 if (args.ContainsKey("region_handle"))
128 UInt64.TryParse(args["region_handle"].AsString(), out RegionHandle); 142 UInt64.TryParse(args["region_handle"].AsString(), out RegionHandle);
@@ -165,6 +179,30 @@ namespace OpenSim.Framework
165 179
166 if (args["throttles"] != null) 180 if (args["throttles"] != null)
167 Throttles = args["throttles"].AsBinary(); 181 Throttles = args["throttles"].AsBinary();
182
183 if (args.ContainsKey("children_seeds") && (args["children_seeds"] != null) &&
184 (args["children_seeds"].Type == OSDType.Array))
185 {
186 OSDArray childrenSeeds = (OSDArray)(args["children_seeds"]);
187 ChildrenCapSeeds = new Dictionary<ulong, string>();
188 foreach (OSD o in childrenSeeds)
189 {
190 if (o.Type == OSDType.Map)
191 {
192 ulong handle = 0;
193 string seed = "";
194 OSDMap pair = (OSDMap)o;
195 if (pair["handle"] != null)
196 if (!UInt64.TryParse(pair["handle"].AsString(), out handle))
197 continue;
198 if (pair["seed"] != null)
199 seed = pair["seed"].AsString();
200 if (!ChildrenCapSeeds.ContainsKey(handle))
201 ChildrenCapSeeds.Add(handle, seed);
202 }
203 }
204 }
205
168 } 206 }
169 207
170 /// <summary> 208 /// <summary>
@@ -317,9 +355,11 @@ namespace OpenSim.Framework
317 public UUID ActiveGroupID; 355 public UUID ActiveGroupID;
318 356
319 public AgentGroupData[] Groups; 357 public AgentGroupData[] Groups;
358 public Dictionary<ulong, string> ChildrenCapSeeds = null;
320 public Animation[] Anims; 359 public Animation[] Anims;
321 public Animation DefaultAnim = null; 360 public Animation DefaultAnim = null;
322 public Animation AnimState = null; 361 public Animation AnimState = null;
362 public Byte MotionState = 0;
323 363
324 public UUID GranterID; 364 public UUID GranterID;
325 public UUID ParentPart; 365 public UUID ParentPart;
@@ -349,8 +389,12 @@ namespace OpenSim.Framework
349 public List<ISceneObject> AttachmentObjects; 389 public List<ISceneObject> AttachmentObjects;
350 public List<string> AttachmentObjectStates; 390 public List<string> AttachmentObjectStates;
351 391
352 public virtual OSDMap Pack() 392 public Dictionary<string, UUID> MovementAnimationOverRides = new Dictionary<string, UUID>();
393
394 public virtual OSDMap Pack(EntityTransferContext ctx)
353 { 395 {
396 int wearablesCount = -1;
397
354// m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data"); 398// m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data");
355 399
356 OSDMap args = new OSDMap(); 400 OSDMap args = new OSDMap();
@@ -399,6 +443,19 @@ namespace OpenSim.Framework
399 args["groups"] = groups; 443 args["groups"] = groups;
400 } 444 }
401 445
446 if (ChildrenCapSeeds != null && ChildrenCapSeeds.Count > 0)
447 {
448 OSDArray childrenSeeds = new OSDArray(ChildrenCapSeeds.Count);
449 foreach (KeyValuePair<ulong, string> kvp in ChildrenCapSeeds)
450 {
451 OSDMap pair = new OSDMap();
452 pair["handle"] = OSD.FromString(kvp.Key.ToString());
453 pair["seed"] = OSD.FromString(kvp.Value);
454 childrenSeeds.Add(pair);
455 }
456 args["children_seeds"] = childrenSeeds;
457 }
458
402 if ((Anims != null) && (Anims.Length > 0)) 459 if ((Anims != null) && (Anims.Length > 0))
403 { 460 {
404 OSDArray anims = new OSDArray(Anims.Length); 461 OSDArray anims = new OSDArray(Anims.Length);
@@ -417,8 +474,28 @@ namespace OpenSim.Framework
417 args["animation_state"] = AnimState.PackUpdateMessage(); 474 args["animation_state"] = AnimState.PackUpdateMessage();
418 } 475 }
419 476
477 if (MovementAnimationOverRides.Count > 0)
478 {
479 OSDArray AOs = new OSDArray(MovementAnimationOverRides.Count);
480 {
481 foreach (KeyValuePair<string, UUID> kvp in MovementAnimationOverRides)
482 {
483 OSDMap ao = new OSDMap(2);
484 ao["state"] = OSD.FromString(kvp.Key);
485 ao["uuid"] = OSD.FromUUID(kvp.Value);
486 AOs.Add(ao);
487 }
488 }
489 args["movementAO"] = AOs;
490 }
491
492 if (MotionState != 0)
493 {
494 args["motion_state"] = OSD.FromInteger(MotionState);
495 }
496
420 if (Appearance != null) 497 if (Appearance != null)
421 args["packed_appearance"] = Appearance.Pack(); 498 args["packed_appearance"] = Appearance.Pack(ctx);
422 499
423 //if ((AgentTextures != null) && (AgentTextures.Length > 0)) 500 //if ((AgentTextures != null) && (AgentTextures.Length > 0))
424 //{ 501 //{
@@ -431,6 +508,8 @@ namespace OpenSim.Framework
431 // The code to pack textures, visuals, wearables and attachments 508 // The code to pack textures, visuals, wearables and attachments
432 // should be removed; packed appearance contains the full appearance 509 // should be removed; packed appearance contains the full appearance
433 // This is retained for backward compatibility only 510 // This is retained for backward compatibility only
511
512/* then lets remove
434 if (Appearance.Texture != null) 513 if (Appearance.Texture != null)
435 { 514 {
436 byte[] rawtextures = Appearance.Texture.GetBytes(); 515 byte[] rawtextures = Appearance.Texture.GetBytes();
@@ -459,7 +538,7 @@ namespace OpenSim.Framework
459 args["attachments"] = attachs; 538 args["attachments"] = attachs;
460 } 539 }
461 // End of code to remove 540 // End of code to remove
462 541*/
463 if ((Controllers != null) && (Controllers.Length > 0)) 542 if ((Controllers != null) && (Controllers.Length > 0))
464 { 543 {
465 OSDArray controls = new OSDArray(Controllers.Length); 544 OSDArray controls = new OSDArray(Controllers.Length);
@@ -507,7 +586,7 @@ namespace OpenSim.Framework
507 /// Avoiding reflection makes it painful to write, but that's the price! 586 /// Avoiding reflection makes it painful to write, but that's the price!
508 /// </summary> 587 /// </summary>
509 /// <param name="hash"></param> 588 /// <param name="hash"></param>
510 public virtual void Unpack(OSDMap args, IScene scene) 589 public virtual void Unpack(OSDMap args, IScene scene, EntityTransferContext ctx)
511 { 590 {
512 //m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data"); 591 //m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data");
513 592
@@ -600,6 +679,29 @@ namespace OpenSim.Framework
600 } 679 }
601 } 680 }
602 681
682 if (args.ContainsKey("children_seeds") && (args["children_seeds"] != null) &&
683 (args["children_seeds"].Type == OSDType.Array))
684 {
685 OSDArray childrenSeeds = (OSDArray)(args["children_seeds"]);
686 ChildrenCapSeeds = new Dictionary<ulong, string>();
687 foreach (OSD o in childrenSeeds)
688 {
689 if (o.Type == OSDType.Map)
690 {
691 ulong handle = 0;
692 string seed = "";
693 OSDMap pair = (OSDMap)o;
694 if (pair["handle"] != null)
695 if (!UInt64.TryParse(pair["handle"].AsString(), out handle))
696 continue;
697 if (pair["seed"] != null)
698 seed = pair["seed"].AsString();
699 if (!ChildrenCapSeeds.ContainsKey(handle))
700 ChildrenCapSeeds.Add(handle, seed);
701 }
702 }
703 }
704
603 if ((args["animations"] != null) && (args["animations"]).Type == OSDType.Array) 705 if ((args["animations"] != null) && (args["animations"]).Type == OSDType.Array)
604 { 706 {
605 OSDArray anims = (OSDArray)(args["animations"]); 707 OSDArray anims = (OSDArray)(args["animations"]);
@@ -638,6 +740,28 @@ namespace OpenSim.Framework
638 } 740 }
639 } 741 }
640 742
743 MovementAnimationOverRides.Clear();
744
745 if (args["movementAO"] != null && args["movementAO"].Type == OSDType.Array)
746 {
747 OSDArray AOs = (OSDArray)(args["movementAO"]);
748 int count = AOs.Count;
749
750 for (int i = 0; i < count; i++)
751 {
752 OSDMap ao = (OSDMap)AOs[i];
753 if (ao["state"] != null && ao["uuid"] != null)
754 {
755 string state = ao["state"].AsString();
756 UUID id = ao["uuid"].AsUUID();
757 MovementAnimationOverRides[state] = id;
758 }
759 }
760 }
761
762 if (args.ContainsKey("motion_state"))
763 MotionState = (byte)args["motion_state"].AsInteger();
764
641 //if ((args["agent_textures"] != null) && (args["agent_textures"]).Type == OSDType.Array) 765 //if ((args["agent_textures"] != null) && (args["agent_textures"]).Type == OSDType.Array)
642 //{ 766 //{
643 // OSDArray textures = (OSDArray)(args["agent_textures"]); 767 // OSDArray textures = (OSDArray)(args["agent_textures"]);
@@ -647,53 +771,67 @@ namespace OpenSim.Framework
647 // AgentTextures[i++] = o.AsUUID(); 771 // AgentTextures[i++] = o.AsUUID();
648 //} 772 //}
649 773
650 Appearance = new AvatarAppearance();
651 774
652 // The code to unpack textures, visuals, wearables and attachments 775 // packed_appearence should contain all appearance information
653 // should be removed; packed appearance contains the full appearance 776 if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map)
654 // This is retained for backward compatibility only
655 if (args["texture_entry"] != null)
656 { 777 {
657 byte[] rawtextures = args["texture_entry"].AsBinary(); 778 m_log.WarnFormat("[CHILDAGENTDATAUPDATE] got packed appearance");
658 Primitive.TextureEntry textures = new Primitive.TextureEntry(rawtextures,0,rawtextures.Length); 779 Appearance = new AvatarAppearance((OSDMap)args["packed_appearance"]);
659 Appearance.SetTextureEntries(textures);
660 } 780 }
781 else
782 {
783 // if missing try the old pack method
784 m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance, checking old method");
661 785
662 if (args["visual_params"] != null) 786 Appearance = new AvatarAppearance();
663 Appearance.SetVisualParams(args["visual_params"].AsBinary());
664 787
665 if ((args["wearables"] != null) && (args["wearables"]).Type == OSDType.Array) 788 // The code to unpack textures, visuals, wearables and attachments
666 { 789 // should be removed; packed appearance contains the full appearance
667 OSDArray wears = (OSDArray)(args["wearables"]); 790 // This is retained for backward compatibility only
668 for (int i = 0; i < wears.Count / 2; i++) 791 if (args["texture_entry"] != null)
669 { 792 {
670 AvatarWearable awear = new AvatarWearable((OSDArray)wears[i]); 793 byte[] rawtextures = args["texture_entry"].AsBinary();
671 Appearance.SetWearable(i,awear); 794 Primitive.TextureEntry textures = new Primitive.TextureEntry(rawtextures, 0, rawtextures.Length);
795 Appearance.SetTextureEntries(textures);
672 } 796 }
673 }
674 797
675 if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array) 798 if (args["visual_params"] != null)
676 { 799 Appearance.SetVisualParams(args["visual_params"].AsBinary());
677 OSDArray attachs = (OSDArray)(args["attachments"]); 800
678 foreach (OSD o in attachs) 801 if ((args["wearables"] != null) && (args["wearables"]).Type == OSDType.Array)
679 { 802 {
680 if (o.Type == OSDType.Map) 803 OSDArray wears = (OSDArray)(args["wearables"]);
804
805 for (int i = 0; i < wears.Count / 2; i++)
681 { 806 {
682 // We know all of these must end up as attachments so we 807 AvatarWearable awear = new AvatarWearable((OSDArray)wears[i]);
683 // append rather than replace to ensure multiple attachments 808 Appearance.SetWearable(i, awear);
684 // per point continues to work
685// m_log.DebugFormat("[CHILDAGENTDATAUPDATE]: Appending attachments for {0}", AgentID);
686 Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o));
687 } 809 }
688 } 810 }
689 }
690 // end of code to remove
691 811
812 if ((args["attachments"] != null) && (args["attachments"]).Type == OSDType.Array)
813 {
814 OSDArray attachs = (OSDArray)(args["attachments"]);
815 foreach (OSD o in attachs)
816 {
817 if (o.Type == OSDType.Map)
818 {
819 // We know all of these must end up as attachments so we
820 // append rather than replace to ensure multiple attachments
821 // per point continues to work
822 // m_log.DebugFormat("[CHILDAGENTDATAUPDATE]: Appending attachments for {0}", AgentID);
823 Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o));
824 }
825 }
826 }
827 // end of code to remove
828 }
829/* moved above
692 if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map) 830 if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map)
693 Appearance = new AvatarAppearance((OSDMap)args["packed_appearance"]); 831 Appearance = new AvatarAppearance((OSDMap)args["packed_appearance"]);
694 else 832 else
695 m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance"); 833 m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance");
696 834*/
697 if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) 835 if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array)
698 { 836 {
699 OSDArray controls = (OSDArray)(args["controllers"]); 837 OSDArray controls = (OSDArray)(args["controllers"]);
@@ -757,14 +895,14 @@ namespace OpenSim.Framework
757 895
758 public class CompleteAgentData : AgentData 896 public class CompleteAgentData : AgentData
759 { 897 {
760 public override OSDMap Pack() 898 public override OSDMap Pack(EntityTransferContext ctx)
761 { 899 {
762 return base.Pack(); 900 return base.Pack(ctx);
763 } 901 }
764 902
765 public override void Unpack(OSDMap map, IScene scene) 903 public override void Unpack(OSDMap map, IScene scene, EntityTransferContext ctx)
766 { 904 {
767 base.Unpack(map, scene); 905 base.Unpack(map, scene, ctx);
768 } 906 }
769 } 907 }
770} 908}
diff --git a/OpenSim/Framework/ColliderData.cs b/OpenSim/Framework/ColliderData.cs
index 1b7b682..00013e1 100644
--- a/OpenSim/Framework/ColliderData.cs
+++ b/OpenSim/Framework/ColliderData.cs
@@ -42,6 +42,7 @@ namespace OpenSim.Framework
42 public Vector3 velVector = Vector3.Zero; 42 public Vector3 velVector = Vector3.Zero;
43 public string nameStr = String.Empty; 43 public string nameStr = String.Empty;
44 public int colliderType = 0; 44 public int colliderType = 0;
45 public int linkNumber;
45 } 46 }
46 47
47 public class ColliderArgs : EventArgs 48 public class ColliderArgs : EventArgs
diff --git a/OpenSim/Framework/ConfigurationMember.cs b/OpenSim/Framework/ConfigurationMember.cs
new file mode 100644
index 0000000..7afa68a
--- /dev/null
+++ b/OpenSim/Framework/ConfigurationMember.cs
@@ -0,0 +1,530 @@
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.Globalization;
31using System.Net;
32using System.Reflection;
33using System.Xml;
34using log4net;
35using OpenMetaverse;
36//using OpenSim.Framework.Console;
37
38namespace OpenSim.Framework
39{
40 public class ConfigurationMember
41 {
42 #region Delegates
43
44 public delegate bool ConfigurationOptionResult(string configuration_key, object configuration_result);
45
46 public delegate void ConfigurationOptionsLoad();
47
48 #endregion
49
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private int cE = 0;
52
53 private string configurationDescription = String.Empty;
54 private string configurationFilename = String.Empty;
55 private XmlNode configurationFromXMLNode = null;
56 private List<ConfigurationOption> configurationOptions = new List<ConfigurationOption>();
57 private IGenericConfig configurationPlugin = null;
58
59 /// <summary>
60 /// This is the default configuration DLL loaded
61 /// </summary>
62 private string configurationPluginFilename = "OpenSim.Framework.Configuration.XML.dll";
63
64 private ConfigurationOptionsLoad loadFunction;
65 private ConfigurationOptionResult resultFunction;
66
67 private bool useConsoleToPromptOnError = true;
68
69 public ConfigurationMember(string configuration_filename, string configuration_description,
70 ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
71 {
72 configurationFilename = configuration_filename;
73 configurationDescription = configuration_description;
74 loadFunction = load_function;
75 resultFunction = result_function;
76 useConsoleToPromptOnError = use_console_to_prompt_on_error;
77 }
78
79 public ConfigurationMember(XmlNode configuration_xml, string configuration_description,
80 ConfigurationOptionsLoad load_function, ConfigurationOptionResult result_function, bool use_console_to_prompt_on_error)
81 {
82 configurationFilename = String.Empty;
83 configurationFromXMLNode = configuration_xml;
84 configurationDescription = configuration_description;
85 loadFunction = load_function;
86 resultFunction = result_function;
87 useConsoleToPromptOnError = use_console_to_prompt_on_error;
88 }
89
90 public void setConfigurationFilename(string filename)
91 {
92 configurationFilename = filename;
93 }
94
95 public void setConfigurationDescription(string desc)
96 {
97 configurationDescription = desc;
98 }
99
100 public void setConfigurationResultFunction(ConfigurationOptionResult result)
101 {
102 resultFunction = result;
103 }
104
105 public void forceConfigurationPluginLibrary(string dll_filename)
106 {
107 configurationPluginFilename = dll_filename;
108 }
109
110 private void checkAndAddConfigOption(ConfigurationOption option)
111 {
112 if ((option.configurationKey != String.Empty && option.configurationQuestion != String.Empty) ||
113 (option.configurationKey != String.Empty && option.configurationUseDefaultNoPrompt))
114 {
115 if (!configurationOptions.Contains(option))
116 {
117 configurationOptions.Add(option);
118 }
119 }
120 else
121 {
122 m_log.Info(
123 "Required fields for adding a configuration option is invalid. Will not add this option (" +
124 option.configurationKey + ")");
125 }
126 }
127
128 public void addConfigurationOption(string configuration_key,
129 ConfigurationOption.ConfigurationTypes configuration_type,
130 string configuration_question, string configuration_default,
131 bool use_default_no_prompt)
132 {
133 ConfigurationOption configOption = new ConfigurationOption();
134 configOption.configurationKey = configuration_key;
135 configOption.configurationQuestion = configuration_question;
136 configOption.configurationDefault = configuration_default;
137 configOption.configurationType = configuration_type;
138 configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
139 configOption.shouldIBeAsked = null; //Assumes true, I can ask whenever
140 checkAndAddConfigOption(configOption);
141 }
142
143 public void addConfigurationOption(string configuration_key,
144 ConfigurationOption.ConfigurationTypes configuration_type,
145 string configuration_question, string configuration_default,
146 bool use_default_no_prompt,
147 ConfigurationOption.ConfigurationOptionShouldBeAsked shouldIBeAskedDelegate)
148 {
149 ConfigurationOption configOption = new ConfigurationOption();
150 configOption.configurationKey = configuration_key;
151 configOption.configurationQuestion = configuration_question;
152 configOption.configurationDefault = configuration_default;
153 configOption.configurationType = configuration_type;
154 configOption.configurationUseDefaultNoPrompt = use_default_no_prompt;
155 configOption.shouldIBeAsked = shouldIBeAskedDelegate;
156 checkAndAddConfigOption(configOption);
157 }
158
159 // TEMP - REMOVE
160 public void performConfigurationRetrieve()
161 {
162 if (cE > 1)
163 m_log.Error("READING CONFIGURATION COUT: " + cE.ToString());
164
165
166 configurationPlugin = LoadConfigDll(configurationPluginFilename);
167 configurationOptions.Clear();
168 if (loadFunction == null)
169 {
170 m_log.Error("Load Function for '" + configurationDescription +
171 "' is null. Refusing to run configuration.");
172 return;
173 }
174
175 if (resultFunction == null)
176 {
177 m_log.Error("Result Function for '" + configurationDescription +
178 "' is null. Refusing to run configuration.");
179 return;
180 }
181
182 //m_log.Debug("[CONFIG]: Calling Configuration Load Function...");
183 loadFunction();
184
185 if (configurationOptions.Count <= 0)
186 {
187 m_log.Error("[CONFIG]: No configuration options were specified for '" + configurationOptions +
188 "'. Refusing to continue configuration.");
189 return;
190 }
191
192 bool useFile = true;
193 if (configurationPlugin == null)
194 {
195 m_log.Error("[CONFIG]: Configuration Plugin NOT LOADED!");
196 return;
197 }
198
199 if (configurationFilename.Trim() != String.Empty)
200 {
201 configurationPlugin.SetFileName(configurationFilename);
202 try
203 {
204 configurationPlugin.LoadData();
205 useFile = true;
206 }
207 catch (XmlException e)
208 {
209 m_log.WarnFormat("[CONFIG] Not using {0}: {1}",
210 configurationFilename,
211 e.Message.ToString());
212 //m_log.Error("Error loading " + configurationFilename + ": " + e.ToString());
213 useFile = false;
214 }
215 }
216 else
217 {
218 if (configurationFromXMLNode != null)
219 {
220 m_log.Info("Loading from XML Node, will not save to the file");
221 configurationPlugin.LoadDataFromString(configurationFromXMLNode.OuterXml);
222 }
223
224 m_log.Info("XML Configuration Filename is not valid; will not save to the file.");
225 useFile = false;
226 }
227
228 foreach (ConfigurationOption configOption in configurationOptions)
229 {
230 bool convertSuccess = false;
231 object return_result = null;
232 string errorMessage = String.Empty;
233 bool ignoreNextFromConfig = false;
234 while (convertSuccess == false)
235 {
236 string console_result = String.Empty;
237 string attribute = null;
238 if (useFile || configurationFromXMLNode != null)
239 {
240 if (!ignoreNextFromConfig)
241 {
242 attribute = configurationPlugin.GetAttribute(configOption.configurationKey);
243 }
244 else
245 {
246 ignoreNextFromConfig = false;
247 }
248 }
249
250 if (attribute == null)
251 {
252 if (configOption.configurationUseDefaultNoPrompt || useConsoleToPromptOnError == false)
253 {
254 console_result = configOption.configurationDefault;
255 }
256 else
257 {
258 if ((configOption.shouldIBeAsked != null &&
259 configOption.shouldIBeAsked(configOption.configurationKey)) ||
260 configOption.shouldIBeAsked == null)
261 {
262 if (configurationDescription.Trim() != String.Empty)
263 {
264 console_result =
265 MainConsole.Instance.CmdPrompt(
266 configurationDescription + ": " + configOption.configurationQuestion,
267 configOption.configurationDefault);
268 }
269 else
270 {
271 console_result =
272 MainConsole.Instance.CmdPrompt(configOption.configurationQuestion,
273 configOption.configurationDefault);
274 }
275 }
276 else
277 {
278 //Dont Ask! Just use default
279 console_result = configOption.configurationDefault;
280 }
281 }
282 }
283 else
284 {
285 console_result = attribute;
286 }
287
288 // if the first character is a "$", assume it's the name
289 // of an environment variable and substitute with the value of that variable
290 if (console_result.StartsWith("$"))
291 console_result = Environment.GetEnvironmentVariable(console_result.Substring(1));
292
293 switch (configOption.configurationType)
294 {
295 case ConfigurationOption.ConfigurationTypes.TYPE_STRING:
296 return_result = console_result;
297 convertSuccess = true;
298 break;
299 case ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY:
300 if (console_result.Length > 0)
301 {
302 return_result = console_result;
303 convertSuccess = true;
304 }
305 errorMessage = "a string that is not empty";
306 break;
307 case ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN:
308 bool boolResult;
309 if (Boolean.TryParse(console_result, out boolResult))
310 {
311 convertSuccess = true;
312 return_result = boolResult;
313 }
314 errorMessage = "'true' or 'false' (Boolean)";
315 break;
316 case ConfigurationOption.ConfigurationTypes.TYPE_BYTE:
317 byte byteResult;
318 if (Byte.TryParse(console_result, out byteResult))
319 {
320 convertSuccess = true;
321 return_result = byteResult;
322 }
323 errorMessage = "a byte (Byte)";
324 break;
325 case ConfigurationOption.ConfigurationTypes.TYPE_CHARACTER:
326 char charResult;
327 if (Char.TryParse(console_result, out charResult))
328 {
329 convertSuccess = true;
330 return_result = charResult;
331 }
332 errorMessage = "a character (Char)";
333 break;
334 case ConfigurationOption.ConfigurationTypes.TYPE_INT16:
335 short shortResult;
336 if (Int16.TryParse(console_result, out shortResult))
337 {
338 convertSuccess = true;
339 return_result = shortResult;
340 }
341 errorMessage = "a signed 32 bit integer (short)";
342 break;
343 case ConfigurationOption.ConfigurationTypes.TYPE_INT32:
344 int intResult;
345 if (Int32.TryParse(console_result, out intResult))
346 {
347 convertSuccess = true;
348 return_result = intResult;
349 }
350 errorMessage = "a signed 32 bit integer (int)";
351 break;
352 case ConfigurationOption.ConfigurationTypes.TYPE_INT64:
353 long longResult;
354 if (Int64.TryParse(console_result, out longResult))
355 {
356 convertSuccess = true;
357 return_result = longResult;
358 }
359 errorMessage = "a signed 32 bit integer (long)";
360 break;
361 case ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS:
362 IPAddress ipAddressResult;
363 if (IPAddress.TryParse(console_result, out ipAddressResult))
364 {
365 convertSuccess = true;
366 return_result = ipAddressResult;
367 }
368 errorMessage = "an IP Address (IPAddress)";
369 break;
370 case ConfigurationOption.ConfigurationTypes.TYPE_UUID:
371 UUID uuidResult;
372 if (UUID.TryParse(console_result, out uuidResult))
373 {
374 convertSuccess = true;
375 return_result = uuidResult;
376 }
377 errorMessage = "a UUID (UUID)";
378 break;
379 case ConfigurationOption.ConfigurationTypes.TYPE_UUID_NULL_FREE:
380 UUID uuidResult2;
381 if (UUID.TryParse(console_result, out uuidResult2))
382 {
383 convertSuccess = true;
384
385 if (uuidResult2 == UUID.Zero)
386 uuidResult2 = UUID.Random();
387
388 return_result = uuidResult2;
389 }
390 errorMessage = "a non-null UUID (UUID)";
391 break;
392 case ConfigurationOption.ConfigurationTypes.TYPE_Vector3:
393 Vector3 vectorResult;
394 if (Vector3.TryParse(console_result, out vectorResult))
395 {
396 convertSuccess = true;
397 return_result = vectorResult;
398 }
399 errorMessage = "a vector (Vector3)";
400 break;
401 case ConfigurationOption.ConfigurationTypes.TYPE_UINT16:
402 ushort ushortResult;
403 if (UInt16.TryParse(console_result, out ushortResult))
404 {
405 convertSuccess = true;
406 return_result = ushortResult;
407 }
408 errorMessage = "an unsigned 16 bit integer (ushort)";
409 break;
410 case ConfigurationOption.ConfigurationTypes.TYPE_UINT32:
411 uint uintResult;
412 if (UInt32.TryParse(console_result, out uintResult))
413 {
414 convertSuccess = true;
415 return_result = uintResult;
416 }
417 errorMessage = "an unsigned 32 bit integer (uint)";
418 break;
419 case ConfigurationOption.ConfigurationTypes.TYPE_UINT64:
420 ulong ulongResult;
421 if (UInt64.TryParse(console_result, out ulongResult))
422 {
423 convertSuccess = true;
424 return_result = ulongResult;
425 }
426 errorMessage = "an unsigned 64 bit integer (ulong)";
427 break;
428 case ConfigurationOption.ConfigurationTypes.TYPE_FLOAT:
429 float floatResult;
430 if (
431 float.TryParse(console_result, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Culture.NumberFormatInfo,
432 out floatResult))
433 {
434 convertSuccess = true;
435 return_result = floatResult;
436 }
437 errorMessage = "a single-precision floating point number (float)";
438 break;
439 case ConfigurationOption.ConfigurationTypes.TYPE_DOUBLE:
440 double doubleResult;
441 if (
442 Double.TryParse(console_result, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, Culture.NumberFormatInfo,
443 out doubleResult))
444 {
445 convertSuccess = true;
446 return_result = doubleResult;
447 }
448 errorMessage = "an double-precision floating point number (double)";
449 break;
450 }
451
452 if (convertSuccess)
453 {
454 if (useFile)
455 {
456 configurationPlugin.SetAttribute(configOption.configurationKey, console_result);
457 }
458
459 if (!resultFunction(configOption.configurationKey, return_result))
460 {
461 m_log.Info(
462 "The handler for the last configuration option denied that input, please try again.");
463 convertSuccess = false;
464 ignoreNextFromConfig = true;
465 }
466 }
467 else
468 {
469 if (configOption.configurationUseDefaultNoPrompt)
470 {
471 m_log.Error(string.Format(
472 "[CONFIG]: [{3}]:[{1}] is not valid default for parameter [{0}].\nThe configuration result must be parsable to {2}.\n",
473 configOption.configurationKey, console_result, errorMessage,
474 configurationFilename));
475 convertSuccess = true;
476 }
477 else
478 {
479 m_log.Warn(string.Format(
480 "[CONFIG]: [{3}]:[{1}] is not a valid value [{0}].\nThe configuration result must be parsable to {2}.\n",
481 configOption.configurationKey, console_result, errorMessage,
482 configurationFilename));
483 ignoreNextFromConfig = true;
484 }
485 }
486 }
487 }
488
489 if (useFile)
490 {
491 configurationPlugin.Commit();
492 configurationPlugin.Close();
493 }
494 }
495
496 private static IGenericConfig LoadConfigDll(string dllName)
497 {
498 Assembly pluginAssembly = Assembly.LoadFrom(dllName);
499 IGenericConfig plug = null;
500
501 foreach (Type pluginType in pluginAssembly.GetTypes())
502 {
503 if (pluginType.IsPublic)
504 {
505 if (!pluginType.IsAbstract)
506 {
507 Type typeInterface = pluginType.GetInterface("IGenericConfig", true);
508
509 if (typeInterface != null)
510 {
511 plug =
512 (IGenericConfig) Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
513 }
514 }
515 }
516 }
517
518 pluginAssembly = null;
519 return plug;
520 }
521
522 public void forceSetConfigurationOption(string configuration_key, string configuration_value)
523 {
524 configurationPlugin.LoadData();
525 configurationPlugin.SetAttribute(configuration_key, configuration_value);
526 configurationPlugin.Commit();
527 configurationPlugin.Close();
528 }
529 }
530}
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index 0f68afe..6b7cdf8 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -83,8 +83,8 @@ namespace OpenSim.Framework.Console
83 = "To enter an argument that contains spaces, surround the argument with double quotes.\nFor example, show object name \"My long object name\"\n"; 83 = "To enter an argument that contains spaces, surround the argument with double quotes.\nFor example, show object name \"My long object name\"\n";
84 84
85 public const string ItemHelpText 85 public const string ItemHelpText
86= @"For more information, type 'help all' to get a list of all commands, 86 = @"For more information, type 'help all' to get a list of all commands,
87 or type help <item>' where <item> is one of the following:"; 87 or type help <item>' where <item> is one of the following:";
88 88
89 /// <value> 89 /// <value>
90 /// Commands organized by keyword in a tree 90 /// Commands organized by keyword in a tree
diff --git a/OpenSim/Framework/CustomTypes.cs b/OpenSim/Framework/CustomTypes.cs
new file mode 100644
index 0000000..d109c26
--- /dev/null
+++ b/OpenSim/Framework/CustomTypes.cs
@@ -0,0 +1,43 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29
30namespace OpenSim.Framework
31{
32 public enum CustomAssetType : sbyte
33 {
34 CustomTypeBase = 0x60,
35 AnimationSet = 0x60,
36 }
37
38 public enum CustomInventoryType : sbyte
39 {
40 CustomTypeBase = 0x60,
41 AnimationSet = 0x60,
42 }
43}
diff --git a/OpenSim/Framework/EntityTransferContext.cs b/OpenSim/Framework/EntityTransferContext.cs
new file mode 100644
index 0000000..860414e
--- /dev/null
+++ b/OpenSim/Framework/EntityTransferContext.cs
@@ -0,0 +1,70 @@
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 OpenMetaverse.StructuredData;
32
33namespace OpenSim.Framework
34{
35 public class EntityTransferContext
36 {
37 public EntityTransferContext()
38 {
39 InboundVersion = VersionInfo.SimulationServiceVersionAcceptedMax;
40 OutboundVersion = VersionInfo.SimulationServiceVersionSupportedMax;
41 WearablesCount = -1;
42 }
43
44 public float InboundVersion { get; set; }
45 public float OutboundVersion { get; set; }
46 public int WearablesCount { get; set; }
47
48 public OSD Pack()
49 {
50 OSDMap data = new OSDMap();
51 data["InboundVersion"] = OSD.FromReal(InboundVersion);
52 data["OutboundVersion"] = OSD.FromReal(OutboundVersion);
53 data["WearablesCount"] = OSD.FromInteger(WearablesCount);
54
55 return data;
56 }
57
58 public void Unpack(OSD data)
59 {
60 OSDMap map = (OSDMap)data;
61
62 if (map.ContainsKey("InboundVersion"))
63 InboundVersion = (float)map["InboundVersion"].AsReal();
64 if (map.ContainsKey("OutboundVersion"))
65 OutboundVersion = (float)map["OutboundVersion"].AsReal();
66 if (map.ContainsKey("WearablesCount"))
67 WearablesCount = map["WearablesCount"].AsInteger();
68 }
69 }
70}
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index 4df7860..4c9f6e9 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -365,9 +365,41 @@ namespace OpenSim.Framework
365 365
366 public bool IsBanned(UUID avatarID) 366 public bool IsBanned(UUID avatarID)
367 { 367 {
368 foreach (EstateBan ban in l_EstateBans) 368 if (!IsEstateManagerOrOwner(avatarID))
369 {
370 foreach (EstateBan ban in l_EstateBans)
371 if (ban.BannedUserID == avatarID)
372 return true;
373 }
374 return false;
375 }
376
377 public bool IsBanned(UUID avatarID, int userFlags)
378 {
379 if (!IsEstateManagerOrOwner(avatarID))
380 {
381 foreach (EstateBan ban in l_EstateBans)
369 if (ban.BannedUserID == avatarID) 382 if (ban.BannedUserID == avatarID)
370 return true; 383 return true;
384
385 if (!HasAccess(avatarID))
386 {
387 if (DenyMinors)
388 {
389 if ((userFlags & 32) == 0)
390 {
391 return true;
392 }
393 }
394 if (DenyAnonymous)
395 {
396 if ((userFlags & 4) == 0)
397 {
398 return true;
399 }
400 }
401 }
402 }
371 return false; 403 return false;
372 } 404 }
373 405
@@ -375,7 +407,7 @@ namespace OpenSim.Framework
375 { 407 {
376 if (ban == null) 408 if (ban == null)
377 return; 409 return;
378 if (!IsBanned(ban.BannedUserID)) 410 if (!IsBanned(ban.BannedUserID, 32)) //Ignore age-based bans
379 l_EstateBans.Add(ban); 411 l_EstateBans.Add(ban);
380 } 412 }
381 413
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index e36edb2..85edce3 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -64,14 +64,15 @@ namespace OpenSim.Framework
64 64
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 CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest);
68
69 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);
70 69
71 public delegate void StartAnim(IClientAPI remoteClient, UUID animID); 70 public delegate void StartAnim(IClientAPI remoteClient, UUID animID);
72 71
73 public delegate void StopAnim(IClientAPI remoteClient, UUID animID); 72 public delegate void StopAnim(IClientAPI remoteClient, UUID animID);
74 73
74 public delegate void ChangeAnim(UUID animID, bool addOrRemove, bool sendPack);
75
75 public delegate void LinkObjects(IClientAPI remoteClient, uint parent, List<uint> children); 76 public delegate void LinkObjects(IClientAPI remoteClient, uint parent, List<uint> children);
76 77
77 public delegate void DelinkObjects(List<uint> primIds, IClientAPI client); 78 public delegate void DelinkObjects(List<uint> primIds, IClientAPI client);
@@ -132,6 +133,8 @@ namespace OpenSim.Framework
132 133
133 public delegate void UpdateVector(uint localID, Vector3 pos, IClientAPI remoteClient); 134 public delegate void UpdateVector(uint localID, Vector3 pos, IClientAPI remoteClient);
134 135
136 public delegate void ClientChangeObject(uint localID, object data ,IClientAPI remoteClient);
137
135 public delegate void UpdatePrimRotation(uint localID, Quaternion rot, IClientAPI remoteClient); 138 public delegate void UpdatePrimRotation(uint localID, Quaternion rot, IClientAPI remoteClient);
136 139
137 public delegate void UpdatePrimSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient); 140 public delegate void UpdatePrimSingleRotation(uint localID, Quaternion rot, IClientAPI remoteClient);
@@ -268,6 +271,9 @@ namespace OpenSim.Framework
268 public delegate void MoveInventoryItem( 271 public delegate void MoveInventoryItem(
269 IClientAPI remoteClient, List<InventoryItemBase> items); 272 IClientAPI remoteClient, List<InventoryItemBase> items);
270 273
274 public delegate void MoveItemsAndLeaveCopy(
275 IClientAPI remoteClient, List<InventoryItemBase> items, UUID destFolder);
276
271 public delegate void RemoveInventoryItem( 277 public delegate void RemoveInventoryItem(
272 IClientAPI remoteClient, List<UUID> itemIDs); 278 IClientAPI remoteClient, List<UUID> itemIDs);
273 279
@@ -443,6 +449,7 @@ namespace OpenSim.Framework
443 public delegate void ClassifiedInfoRequest(UUID classifiedID, IClientAPI client); 449 public delegate void ClassifiedInfoRequest(UUID classifiedID, IClientAPI client);
444 public delegate void ClassifiedInfoUpdate(UUID classifiedID, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, Vector3 globalPos, byte classifiedFlags, int price, IClientAPI client); 450 public delegate void ClassifiedInfoUpdate(UUID classifiedID, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, Vector3 globalPos, byte classifiedFlags, int price, IClientAPI client);
445 public delegate void ClassifiedDelete(UUID classifiedID, IClientAPI client); 451 public delegate void ClassifiedDelete(UUID classifiedID, IClientAPI client);
452 public delegate void ClassifiedGodDelete(UUID classifiedID, UUID queryID, IClientAPI client);
446 453
447 public delegate void EventNotificationAddRequest(uint EventID, IClientAPI client); 454 public delegate void EventNotificationAddRequest(uint EventID, IClientAPI client);
448 public delegate void EventNotificationRemoveRequest(uint EventID, IClientAPI client); 455 public delegate void EventNotificationRemoveRequest(uint EventID, IClientAPI client);
@@ -465,9 +472,9 @@ namespace OpenSim.Framework
465 472
466 public delegate void AgentFOV(IClientAPI client, float verticalAngle); 473 public delegate void AgentFOV(IClientAPI client, float verticalAngle);
467 474
468 public delegate void MuteListEntryUpdate(IClientAPI client, UUID MuteID, string Name, int Flags,UUID AgentID); 475 public delegate void MuteListEntryUpdate(IClientAPI client, UUID MuteID, string Name, int type, uint flags);
469 476
470 public delegate void MuteListEntryRemove(IClientAPI client, UUID MuteID, string Name, UUID AgentID); 477 public delegate void MuteListEntryRemove(IClientAPI client, UUID MuteID, string Name);
471 478
472 public delegate void AvatarInterestReply(IClientAPI client,UUID target, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages); 479 public delegate void AvatarInterestReply(IClientAPI client,UUID target, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages);
473 480
@@ -505,6 +512,7 @@ namespace OpenSim.Framework
505 public delegate void SimWideDeletesDelegate(IClientAPI client,UUID agentID, int flags, UUID targetID); 512 public delegate void SimWideDeletesDelegate(IClientAPI client,UUID agentID, int flags, UUID targetID);
506 513
507 public delegate void SendPostcard(IClientAPI client); 514 public delegate void SendPostcard(IClientAPI client);
515 public delegate void ChangeInventoryItemFlags(IClientAPI client, UUID itemID, uint flags);
508 516
509 #endregion 517 #endregion
510 518
@@ -734,6 +742,8 @@ namespace OpenSim.Framework
734 742
735 IScene Scene { get; } 743 IScene Scene { get; }
736 744
745 List<uint> SelectedObjects { get; }
746
737 // [Obsolete("LLClientView Specific - Replace with ???")] 747 // [Obsolete("LLClientView Specific - Replace with ???")]
738 int NextAnimationSequenceNumber { get; } 748 int NextAnimationSequenceNumber { get; }
739 749
@@ -747,6 +757,8 @@ namespace OpenSim.Framework
747 /// </summary> 757 /// </summary>
748 bool IsActive { get; set; } 758 bool IsActive { get; set; }
749 759
760 int PingTimeMS { get; }
761
750 /// <summary> 762 /// <summary>
751 /// Set if the client is closing due to a logout request 763 /// Set if the client is closing due to a logout request
752 /// </summary> 764 /// </summary>
@@ -794,6 +806,7 @@ namespace OpenSim.Framework
794 event ObjectDrop OnObjectDrop; 806 event ObjectDrop OnObjectDrop;
795 event StartAnim OnStartAnim; 807 event StartAnim OnStartAnim;
796 event StopAnim OnStopAnim; 808 event StopAnim OnStopAnim;
809 event ChangeAnim OnChangeAnim;
797 event LinkObjects OnLinkObjects; 810 event LinkObjects OnLinkObjects;
798 event DelinkObjects OnDelinkObjects; 811 event DelinkObjects OnDelinkObjects;
799 event RequestMapBlocks OnRequestMapBlocks; 812 event RequestMapBlocks OnRequestMapBlocks;
@@ -860,6 +873,7 @@ namespace OpenSim.Framework
860 event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; 873 event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
861 event UpdatePrimFlags OnUpdatePrimFlags; 874 event UpdatePrimFlags OnUpdatePrimFlags;
862 event UpdatePrimTexture OnUpdatePrimTexture; 875 event UpdatePrimTexture OnUpdatePrimTexture;
876 event ClientChangeObject onClientChangeObject;
863 event UpdateVector OnUpdatePrimGroupPosition; 877 event UpdateVector OnUpdatePrimGroupPosition;
864 event UpdateVector OnUpdatePrimSinglePosition; 878 event UpdateVector OnUpdatePrimSinglePosition;
865 event UpdatePrimRotation OnUpdatePrimGroupRotation; 879 event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -884,6 +898,7 @@ namespace OpenSim.Framework
884 event RequestTaskInventory OnRequestTaskInventory; 898 event RequestTaskInventory OnRequestTaskInventory;
885 event UpdateInventoryItem OnUpdateInventoryItem; 899 event UpdateInventoryItem OnUpdateInventoryItem;
886 event CopyInventoryItem OnCopyInventoryItem; 900 event CopyInventoryItem OnCopyInventoryItem;
901 event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
887 event MoveInventoryItem OnMoveInventoryItem; 902 event MoveInventoryItem OnMoveInventoryItem;
888 event RemoveInventoryFolder OnRemoveInventoryFolder; 903 event RemoveInventoryFolder OnRemoveInventoryFolder;
889 event RemoveInventoryItem OnRemoveInventoryItem; 904 event RemoveInventoryItem OnRemoveInventoryItem;
@@ -1002,7 +1017,7 @@ namespace OpenSim.Framework
1002 event ClassifiedInfoRequest OnClassifiedInfoRequest; 1017 event ClassifiedInfoRequest OnClassifiedInfoRequest;
1003 event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 1018 event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
1004 event ClassifiedDelete OnClassifiedDelete; 1019 event ClassifiedDelete OnClassifiedDelete;
1005 event ClassifiedDelete OnClassifiedGodDelete; 1020 event ClassifiedGodDelete OnClassifiedGodDelete;
1006 1021
1007 event EventNotificationAddRequest OnEventNotificationAddRequest; 1022 event EventNotificationAddRequest OnEventNotificationAddRequest;
1008 event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 1023 event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -1041,11 +1056,12 @@ namespace OpenSim.Framework
1041 event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 1056 event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
1042 event SimWideDeletesDelegate OnSimWideDeletes; 1057 event SimWideDeletesDelegate OnSimWideDeletes;
1043 event SendPostcard OnSendPostcard; 1058 event SendPostcard OnSendPostcard;
1059 event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
1044 event MuteListEntryUpdate OnUpdateMuteListEntry; 1060 event MuteListEntryUpdate OnUpdateMuteListEntry;
1045 event MuteListEntryRemove OnRemoveMuteListEntry; 1061 event MuteListEntryRemove OnRemoveMuteListEntry;
1046 event GodlikeMessage onGodlikeMessage; 1062 event GodlikeMessage onGodlikeMessage;
1047 event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 1063 event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
1048 1064 event GenericCall2 OnUpdateThrottles;
1049 /// <summary> 1065 /// <summary>
1050 /// Set the debug level at which packet output should be printed to console. 1066 /// Set the debug level at which packet output should be printed to console.
1051 /// </summary> 1067 /// </summary>
@@ -1066,7 +1082,7 @@ namespace OpenSim.Framework
1066 /// If true, attempts the close without checking active status. You do not want to try this except as a last 1082 /// If true, attempts the close without checking active status. You do not want to try this except as a last
1067 /// ditch attempt where Active == false but the ScenePresence still exists. 1083 /// ditch attempt where Active == false but the ScenePresence still exists.
1068 /// </param> 1084 /// </param>
1069 void Close(bool force); 1085 void Close(bool sendStop, bool force);
1070 1086
1071 void Kick(string message); 1087 void Kick(string message);
1072 1088
@@ -1102,6 +1118,8 @@ namespace OpenSim.Framework
1102 /// <param name="localID"></param> 1118 /// <param name="localID"></param>
1103 void SendKillObject(List<uint> localID); 1119 void SendKillObject(List<uint> localID);
1104 1120
1121 void SendPartFullUpdate(ISceneEntity ent, uint? parentID);
1122
1105 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); 1123 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
1106 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); 1124 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);
1107 1125
@@ -1125,6 +1143,8 @@ namespace OpenSim.Framework
1125 void SendGenericMessage(string method, UUID invoice, List<string> message); 1143 void SendGenericMessage(string method, UUID invoice, List<string> message);
1126 void SendGenericMessage(string method, UUID invoice, List<byte[]> message); 1144 void SendGenericMessage(string method, UUID invoice, List<byte[]> message);
1127 1145
1146 bool CanSendLayerData();
1147
1128 void SendLayerData(float[] map); 1148 void SendLayerData(float[] map);
1129 void SendLayerData(int px, int py, float[] map); 1149 void SendLayerData(int px, int py, float[] map);
1130 1150
@@ -1168,6 +1188,10 @@ namespace OpenSim.Framework
1168 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); 1188 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
1169 1189
1170 void SetChildAgentThrottle(byte[] throttle); 1190 void SetChildAgentThrottle(byte[] throttle);
1191 void SetChildAgentThrottle(byte[] throttle,float factor);
1192
1193 void SetAgentThrottleSilent(int throttle, int setting);
1194 int GetAgentThrottleSilent(int throttle);
1171 1195
1172 void SendAvatarDataImmediate(ISceneEntity avatar); 1196 void SendAvatarDataImmediate(ISceneEntity avatar);
1173 1197
@@ -1192,6 +1216,7 @@ namespace OpenSim.Framework
1192 /// </summary> 1216 /// </summary>
1193 /// <param name="Item"></param> 1217 /// <param name="Item"></param>
1194 void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId); 1218 void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId);
1219 void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId);
1195 1220
1196 void SendRemoveInventoryItem(UUID itemID); 1221 void SendRemoveInventoryItem(UUID itemID);
1197 1222
@@ -1211,7 +1236,7 @@ namespace OpenSim.Framework
1211 /// <param name="node"></param> 1236 /// <param name="node"></param>
1212 void SendBulkUpdateInventory(InventoryNodeBase node); 1237 void SendBulkUpdateInventory(InventoryNodeBase node);
1213 1238
1214 void SendXferPacket(ulong xferID, uint packet, byte[] data); 1239 void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory);
1215 1240
1216 void SendAbortXferPacket(ulong xferID); 1241 void SendAbortXferPacket(ulong xferID);
1217 1242
@@ -1367,6 +1392,8 @@ namespace OpenSim.Framework
1367 1392
1368 void SendAgentOnline(UUID[] agentIDs); 1393 void SendAgentOnline(UUID[] agentIDs);
1369 1394
1395 void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY);
1396
1370 void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, 1397 void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
1371 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook); 1398 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook);
1372 1399
@@ -1432,6 +1459,7 @@ namespace OpenSim.Framework
1432 void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags); 1459 void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags);
1433 1460
1434 void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data); 1461 void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data);
1462 void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data);
1435 void SendOfferCallingCard(UUID srcID, UUID transactionID); 1463 void SendOfferCallingCard(UUID srcID, UUID transactionID);
1436 void SendAcceptCallingCard(UUID transactionID); 1464 void SendAcceptCallingCard(UUID transactionID);
1437 void SendDeclineCallingCard(UUID transactionID); 1465 void SendDeclineCallingCard(UUID transactionID);
diff --git a/OpenSim/Framework/ILandChannel.cs b/OpenSim/Framework/ILandChannel.cs
index c46c03c..63cc7eb 100644
--- a/OpenSim/Framework/ILandChannel.cs
+++ b/OpenSim/Framework/ILandChannel.cs
@@ -93,5 +93,7 @@ namespace OpenSim.Region.Framework.Interfaces
93 93
94 void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id); 94 void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id);
95 void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id); 95 void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id);
96 void sendClientInitialLandInfo(IClientAPI remoteClient);
97
96 } 98 }
97} 99}
diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs
index 8465c86..db1496c 100644
--- a/OpenSim/Framework/ILandObject.cs
+++ b/OpenSim/Framework/ILandObject.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Framework
68 void SendLandUpdateToAvatarsOverMe(); 68 void SendLandUpdateToAvatarsOverMe();
69 69
70 void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client); 70 void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client);
71 void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client); 71 bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay);
72 bool IsEitherBannedOrRestricted(UUID avatar); 72 bool IsEitherBannedOrRestricted(UUID avatar);
73 bool IsBannedFromLand(UUID avatar); 73 bool IsBannedFromLand(UUID avatar);
74 bool CanBeOnThisLand(UUID avatar, float posHeight); 74 bool CanBeOnThisLand(UUID avatar, float posHeight);
diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs
index 52f3e83..55c9613 100644
--- a/OpenSim/Framework/IMoneyModule.cs
+++ b/OpenSim/Framework/IMoneyModule.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Framework
33 public interface IMoneyModule 33 public interface IMoneyModule
34 { 34 {
35 bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, 35 bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID,
36 int amount); 36 int amount, UUID txn, out string reason);
37 37
38 int GetBalance(UUID agentID); 38 int GetBalance(UUID agentID);
39 bool UploadCovered(UUID agentID, int amount); 39 bool UploadCovered(UUID agentID, int amount);
@@ -41,6 +41,7 @@ namespace OpenSim.Framework
41 void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type); 41 void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type);
42 void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData); 42 void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData);
43 void ApplyUploadCharge(UUID agentID, int amount, string text); 43 void ApplyUploadCharge(UUID agentID, int amount, string text);
44 void MoveMoney(UUID fromUser, UUID toUser, int amount, string text);
44 45
45 int UploadCharge { get; } 46 int UploadCharge { get; }
46 int GroupCreationCharge { get; } 47 int GroupCreationCharge { get; }
diff --git a/OpenSim/Framework/ISceneAgent.cs b/OpenSim/Framework/ISceneAgent.cs
index ca1399c..be11931 100644
--- a/OpenSim/Framework/ISceneAgent.cs
+++ b/OpenSim/Framework/ISceneAgent.cs
@@ -66,19 +66,14 @@ namespace OpenSim.Framework
66 AvatarAppearance Appearance { get; set; } 66 AvatarAppearance Appearance { get; set; }
67 67
68 /// <summary> 68 /// <summary>
69 /// Set if initial data about the scene (avatars, objects) has been sent to the client.
70 /// </summary>
71 bool SentInitialDataToClient { get; }
72
73 /// <summary>
74 /// Send initial scene data to the client controlling this agent 69 /// Send initial scene data to the client controlling this agent
75 /// </summary> 70 /// </summary>
76 /// <remarks> 71 /// <remarks>
77 /// This includes scene object data and the appearance data of other avatars. 72 /// This includes scene object data and the appearance data of other avatars.
78 /// </remarks> 73 /// </remarks>
79 void SendInitialDataToClient(); 74 void SendInitialDataToMe();
80 75
81 /// <summary> 76 /// <summary>
82 /// Direction in which the scene presence is looking. 77 /// Direction in which the scene presence is looking.
83 /// </summary> 78 /// </summary>
84 /// <remarks>Will be Vector3.Zero for a child agent.</remarks> 79 /// <remarks>Will be Vector3.Zero for a child agent.</remarks>
diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs
index fc02f33..4fbbbc1 100644
--- a/OpenSim/Framework/LandData.cs
+++ b/OpenSim/Framework/LandData.cs
@@ -67,9 +67,9 @@ namespace OpenSim.Framework
67 67
68 private uint _flags = (uint)ParcelFlags.AllowFly | (uint)ParcelFlags.AllowLandmark | 68 private uint _flags = (uint)ParcelFlags.AllowFly | (uint)ParcelFlags.AllowLandmark |
69 (uint)ParcelFlags.AllowAPrimitiveEntry | 69 (uint)ParcelFlags.AllowAPrimitiveEntry |
70 (uint)ParcelFlags.AllowDeedToGroup | (uint)ParcelFlags.AllowTerraform | 70 (uint)ParcelFlags.AllowDeedToGroup |
71 (uint)ParcelFlags.CreateObjects | (uint)ParcelFlags.AllowOtherScripts | 71 (uint)ParcelFlags.CreateObjects | (uint)ParcelFlags.AllowOtherScripts |
72 (uint)ParcelFlags.SoundLocal | (uint)ParcelFlags.AllowVoiceChat; 72 (uint)ParcelFlags.AllowVoiceChat;
73 73
74 private byte _landingType = 0; 74 private byte _landingType = 0;
75 private string _name = "Your Parcel"; 75 private string _name = "Your Parcel";
@@ -99,6 +99,10 @@ namespace OpenSim.Framework
99 private bool _obscureMedia = false; 99 private bool _obscureMedia = false;
100 private float _dwell = 0; 100 private float _dwell = 0;
101 101
102 public bool SeeAVs { get; set; }
103 public bool AnyAVSounds { get; set; }
104 public bool GroupAVSounds { get; set; }
105
102 /// <summary> 106 /// <summary>
103 /// Traffic count of parcel 107 /// Traffic count of parcel
104 /// </summary> 108 /// </summary>
@@ -728,6 +732,9 @@ namespace OpenSim.Framework
728 public LandData() 732 public LandData()
729 { 733 {
730 _globalID = UUID.Random(); 734 _globalID = UUID.Random();
735 SeeAVs = true;
736 AnyAVSounds = true;
737 GroupAVSounds = true;
731 } 738 }
732 739
733 /// <summary> 740 /// <summary>
@@ -778,6 +785,9 @@ namespace OpenSim.Framework
778 landData._simwideArea = _simwideArea; 785 landData._simwideArea = _simwideArea;
779 landData._simwidePrims = _simwidePrims; 786 landData._simwidePrims = _simwidePrims;
780 landData._dwell = _dwell; 787 landData._dwell = _dwell;
788 landData.SeeAVs = SeeAVs;
789 landData.AnyAVSounds = AnyAVSounds;
790 landData.GroupAVSounds = GroupAVSounds;
781 791
782 landData._parcelAccessList.Clear(); 792 landData._parcelAccessList.Clear();
783 foreach (LandAccessEntry entry in _parcelAccessList) 793 foreach (LandAccessEntry entry in _parcelAccessList)
@@ -793,21 +803,21 @@ namespace OpenSim.Framework
793 return landData; 803 return landData;
794 } 804 }
795 805
796 public void ToXml(XmlWriter xmlWriter) 806// public void ToXml(XmlWriter xmlWriter)
797 { 807// {
798 serializer.Serialize(xmlWriter, this); 808// serializer.Serialize(xmlWriter, this);
799 } 809// }
800 810
801 /// <summary> 811 /// <summary>
802 /// Restore a LandData object from the serialized xml representation. 812 /// Restore a LandData object from the serialized xml representation.
803 /// </summary> 813 /// </summary>
804 /// <param name="xmlReader"></param> 814 /// <param name="xmlReader"></param>
805 /// <returns></returns> 815 /// <returns></returns>
806 public static LandData FromXml(XmlReader xmlReader) 816// public static LandData FromXml(XmlReader xmlReader)
807 { 817// {
808 LandData land = (LandData)serializer.Deserialize(xmlReader); 818// LandData land = (LandData)serializer.Deserialize(xmlReader);
809 819//
810 return land; 820// return land;
811 } 821// }
812 } 822 }
813} 823}
diff --git a/OpenSim/Framework/LandUpdateArgs.cs b/OpenSim/Framework/LandUpdateArgs.cs
index 7d6c4f2..a48b8bf 100644
--- a/OpenSim/Framework/LandUpdateArgs.cs
+++ b/OpenSim/Framework/LandUpdateArgs.cs
@@ -56,5 +56,8 @@ namespace OpenSim.Framework
56 public bool MediaLoop; 56 public bool MediaLoop;
57 public bool ObscureMusic; 57 public bool ObscureMusic;
58 public bool ObscureMedia; 58 public bool ObscureMedia;
59 public bool SeeAVs;
60 public bool AnyAVSounds;
61 public bool GroupAVSounds;
59 } 62 }
60} 63}
diff --git a/OpenSim/Framework/LocklessQueue.cs b/OpenSim/Framework/LocklessQueue.cs
index 84f887c..9bd9baf 100644
--- a/OpenSim/Framework/LocklessQueue.cs
+++ b/OpenSim/Framework/LocklessQueue.cs
@@ -29,7 +29,7 @@ using System.Threading;
29 29
30namespace OpenSim.Framework 30namespace OpenSim.Framework
31{ 31{
32 public sealed class LocklessQueue<T> 32 public class LocklessQueue<T>
33 { 33 {
34 private sealed class SingleLinkNode 34 private sealed class SingleLinkNode
35 { 35 {
@@ -41,7 +41,7 @@ namespace OpenSim.Framework
41 SingleLinkNode tail; 41 SingleLinkNode tail;
42 int count; 42 int count;
43 43
44 public int Count { get { return count; } } 44 public virtual int Count { get { return count; } }
45 45
46 public LocklessQueue() 46 public LocklessQueue()
47 { 47 {
@@ -76,7 +76,7 @@ namespace OpenSim.Framework
76 Interlocked.Increment(ref count); 76 Interlocked.Increment(ref count);
77 } 77 }
78 78
79 public bool Dequeue(out T item) 79 public virtual bool Dequeue(out T item)
80 { 80 {
81 item = default(T); 81 item = default(T);
82 SingleLinkNode oldHead = null; 82 SingleLinkNode oldHead = null;
@@ -136,4 +136,4 @@ namespace OpenSim.Framework
136 (object)Interlocked.CompareExchange<SingleLinkNode>(ref location, newValue, comparand); 136 (object)Interlocked.CompareExchange<SingleLinkNode>(ref location, newValue, comparand);
137 } 137 }
138 } 138 }
139} \ No newline at end of file 139}
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 20495f6..96536e8 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -43,7 +43,6 @@ namespace OpenSim.Framework.Monitoring
43 StringBuilder sb = new StringBuilder(Environment.NewLine); 43 StringBuilder sb = new StringBuilder(Environment.NewLine);
44 sb.Append("MEMORY STATISTICS"); 44 sb.Append("MEMORY STATISTICS");
45 sb.Append(Environment.NewLine); 45 sb.Append(Environment.NewLine);
46
47 sb.AppendFormat( 46 sb.AppendFormat(
48 "Heap allocated to OpenSim : {0} MB\n", 47 "Heap allocated to OpenSim : {0} MB\n",
49 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); 48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
@@ -56,9 +55,23 @@ namespace OpenSim.Framework.Monitoring
56 "Average heap allocation rate: {0} MB/s\n", 55 "Average heap allocation rate: {0} MB/s\n",
57 Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3)); 56 Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
58 57
59 sb.AppendFormat( 58 Process myprocess = Process.GetCurrentProcess();
60 "Process memory : {0} MB\n", 59 if (!myprocess.HasExited)
61 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)); 60 {
61 myprocess.Refresh();
62 sb.AppendFormat(
63 "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
64 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0),
65 Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0),
66 Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0));
67 sb.AppendFormat(
68 "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
69 Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0),
70 Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0),
71 Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0));
72 }
73 else
74 sb.Append("Process reported as Exited \n");
62 75
63 return sb.ToString(); 76 return sb.ToString();
64 } 77 }
diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
index 77315bb..be4a8b4 100644
--- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
@@ -249,6 +249,49 @@ namespace OpenSim.Framework.Monitoring
249 (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); 249 (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
250 MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory, 250 MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory,
251 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); 251 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
252
253 MakeStat("ProcessResident", null, "MB", ContainerProcess,
254 (s) =>
255 {
256 Process myprocess = Process.GetCurrentProcess();
257 myprocess.Refresh();
258 s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0);
259 });
260 MakeStat("ProcessPaged", null, "MB", ContainerProcess,
261 (s) =>
262 {
263 Process myprocess = Process.GetCurrentProcess();
264 myprocess.Refresh();
265 s.Value = Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0);
266 });
267 MakeStat("ProcessVirtual", null, "MB", ContainerProcess,
268 (s) =>
269 {
270 Process myprocess = Process.GetCurrentProcess();
271 myprocess.Refresh();
272 s.Value = Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0);
273 });
274 MakeStat("PeakProcessResident", null, "MB", ContainerProcess,
275 (s) =>
276 {
277 Process myprocess = Process.GetCurrentProcess();
278 myprocess.Refresh();
279 s.Value = Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0);
280 });
281 MakeStat("PeakProcessPaged", null, "MB", ContainerProcess,
282 (s) =>
283 {
284 Process myprocess = Process.GetCurrentProcess();
285 myprocess.Refresh();
286 s.Value = Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0);
287 });
288 MakeStat("PeakProcessVirtual", null, "MB", ContainerProcess,
289 (s) =>
290 {
291 Process myprocess = Process.GetCurrentProcess();
292 myprocess.Refresh();
293 s.Value = Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0);
294 });
252 } 295 }
253 296
254 // Notes on performance counters: 297 // Notes on performance counters:
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index e4df7ee..08c2409 100755
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -34,6 +34,7 @@ using OpenMetaverse;
34using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
35using OpenSim.Framework.Monitoring.Interfaces; 35using OpenSim.Framework.Monitoring.Interfaces;
36 36
37
37namespace OpenSim.Framework.Monitoring 38namespace OpenSim.Framework.Monitoring
38{ 39{
39 /// <summary> 40 /// <summary>
@@ -71,6 +72,11 @@ namespace OpenSim.Framework.Monitoring
71 private volatile float pendingDownloads; 72 private volatile float pendingDownloads;
72 private volatile float pendingUploads; 73 private volatile float pendingUploads;
73 private volatile float activeScripts; 74 private volatile float activeScripts;
75 private volatile float spareTime;
76 private volatile float sleepTime;
77 private volatile float physicsStep;
78
79
74 private volatile float scriptLinesPerSecond; 80 private volatile float scriptLinesPerSecond;
75 private volatile float m_frameDilation; 81 private volatile float m_frameDilation;
76 private volatile float m_usersLoggingIn; 82 private volatile float m_usersLoggingIn;
@@ -253,7 +259,7 @@ namespace OpenSim.Framework.Monitoring
253 /// <param name="pack"></param> 259 /// <param name="pack"></param>
254 public void ReceiveClassicSimStatsPacket(SimStats stats) 260 public void ReceiveClassicSimStatsPacket(SimStats stats)
255 { 261 {
256 // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original 262 // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original
257 // SimStatsPacket that was being used). 263 // SimStatsPacket that was being used).
258 264
259 // For an unknown reason the original designers decided not to 265 // For an unknown reason the original designers decided not to
@@ -270,8 +276,8 @@ namespace OpenSim.Framework.Monitoring
270 totalFrameTime = stats.StatsBlock[8].StatValue; 276 totalFrameTime = stats.StatsBlock[8].StatValue;
271 netFrameTime = stats.StatsBlock[9].StatValue; 277 netFrameTime = stats.StatsBlock[9].StatValue;
272 physicsFrameTime = stats.StatsBlock[10].StatValue; 278 physicsFrameTime = stats.StatsBlock[10].StatValue;
273 otherFrameTime = stats.StatsBlock[11].StatValue; 279 imageFrameTime = stats.StatsBlock[11].StatValue;
274 imageFrameTime = stats.StatsBlock[12].StatValue; 280 otherFrameTime = stats.StatsBlock[12].StatValue;
275 inPacketsPerSecond = stats.StatsBlock[13].StatValue; 281 inPacketsPerSecond = stats.StatsBlock[13].StatValue;
276 outPacketsPerSecond = stats.StatsBlock[14].StatValue; 282 outPacketsPerSecond = stats.StatsBlock[14].StatValue;
277 unackedBytes = stats.StatsBlock[15].StatValue; 283 unackedBytes = stats.StatsBlock[15].StatValue;
@@ -279,12 +285,16 @@ namespace OpenSim.Framework.Monitoring
279 pendingDownloads = stats.StatsBlock[17].StatValue; 285 pendingDownloads = stats.StatsBlock[17].StatValue;
280 pendingUploads = stats.StatsBlock[18].StatValue; 286 pendingUploads = stats.StatsBlock[18].StatValue;
281 activeScripts = stats.StatsBlock[19].StatValue; 287 activeScripts = stats.StatsBlock[19].StatValue;
282 scriptLinesPerSecond = stats.StatsBlock[20].StatValue; 288 sleepTime = stats.StatsBlock[20].StatValue;
283 m_frameDilation = stats.StatsBlock[22].StatValue; 289 spareTime = stats.StatsBlock[21].StatValue;
284 m_usersLoggingIn = stats.StatsBlock[23].StatValue; 290 physicsStep = stats.StatsBlock[22].StatValue;
285 m_totalGeoPrims = stats.StatsBlock[24].StatValue; 291
286 m_totalMeshes = stats.StatsBlock[25].StatValue; 292 scriptLinesPerSecond = stats.ExtraStatsBlock[0].StatValue;
287 m_inUseThreads = stats.StatsBlock[26].StatValue; 293 m_frameDilation = stats.ExtraStatsBlock[1].StatValue;
294 m_usersLoggingIn = stats.ExtraStatsBlock[2].StatValue;
295 m_totalGeoPrims = stats.ExtraStatsBlock[3].StatValue;
296 m_totalMeshes = stats.ExtraStatsBlock[4].StatValue;
297 m_inUseThreads = stats.ExtraStatsBlock[5].StatValue;
288 } 298 }
289 299
290 /// <summary> 300 /// <summary>
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index a7cb2a6..916fa53 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -239,6 +239,17 @@ namespace OpenSim.Framework.Monitoring
239 return sb.ToString(); 239 return sb.ToString();
240 } 240 }
241 241
242 public virtual OSDMap ToBriefOSDMap()
243 {
244 OSDMap ret = new OSDMap();
245
246 ret.Add("Value", OSD.FromReal(Value));
247
248 double lastChangeOverTime, averageChangeOverTime;
249
250 return ret;
251 }
252
242 public virtual OSDMap ToOSDMap() 253 public virtual OSDMap ToOSDMap()
243 { 254 {
244 OSDMap ret = new OSDMap(); 255 OSDMap ret = new OSDMap();
@@ -323,4 +334,4 @@ namespace OpenSim.Framework.Monitoring
323 } 334 }
324 } 335 }
325 } 336 }
326} \ No newline at end of file 337}
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 3136ee8..d0d1947 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -283,7 +283,7 @@ namespace OpenSim.Framework.Monitoring
283 if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName)) 283 if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName))
284 continue; 284 continue;
285 285
286 statMap.Add(statName, theStats[statName].ToOSDMap()); 286 statMap.Add(statName, theStats[statName].ToBriefOSDMap());
287 } 287 }
288 288
289 contMap.Add(contName, statMap); 289 contMap.Add(contName, statMap);
@@ -554,4 +554,4 @@ namespace OpenSim.Framework.Monitoring
554 Debug, 554 Debug,
555 Info 555 Info
556 } 556 }
557} \ No newline at end of file 557}
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index a644fa5..4485a9c 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -335,7 +335,9 @@ namespace OpenSim.Framework.Monitoring
335 335
336 lock (m_threads) 336 lock (m_threads)
337 { 337 {
338 foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) 338 // get a copy since we may change m_threads
339 List<ThreadWatchdogInfo> threadsInfo = m_threads.Values.ToList();
340 foreach (ThreadWatchdogInfo threadInfo in threadsInfo)
339 { 341 {
340 if (threadInfo.Thread.ThreadState == ThreadState.Stopped) 342 if (threadInfo.Thread.ThreadState == ThreadState.Stopped)
341 { 343 {
@@ -377,4 +379,4 @@ namespace OpenSim.Framework.Monitoring
377 m_watchdogTimer.Start(); 379 m_watchdogTimer.Start();
378 } 380 }
379 } 381 }
380} \ No newline at end of file 382}
diff --git a/OpenSim/Framework/NetworkServersInfo.cs b/OpenSim/Framework/NetworkServersInfo.cs
index 4b7d4c7..dfe9695 100644
--- a/OpenSim/Framework/NetworkServersInfo.cs
+++ b/OpenSim/Framework/NetworkServersInfo.cs
@@ -41,6 +41,7 @@ namespace OpenSim.Framework
41 41
42 // "Out of band" managemnt https 42 // "Out of band" managemnt https
43 public bool ssl_listener = false; 43 public bool ssl_listener = false;
44 public bool ssl_external = false;
44 public uint https_port = 0; 45 public uint https_port = 0;
45 public string cert_path = String.Empty; 46 public string cert_path = String.Empty;
46 public string cert_pass = String.Empty; 47 public string cert_pass = String.Empty;
@@ -64,6 +65,7 @@ namespace OpenSim.Framework
64 65
65 // "Out of band management https" 66 // "Out of band management https"
66 ssl_listener = config.Configs["Network"].GetBoolean("https_listener",false); 67 ssl_listener = config.Configs["Network"].GetBoolean("https_listener",false);
68 ssl_external = config.Configs["Network"].GetBoolean("https_external",false);
67 if( ssl_listener) 69 if( ssl_listener)
68 { 70 {
69 cert_path = config.Configs["Network"].GetString("cert_path",String.Empty); 71 cert_path = config.Configs["Network"].GetString("cert_path",String.Empty);
diff --git a/OpenSim/Framework/OSChatMessage.cs b/OpenSim/Framework/OSChatMessage.cs
index 455756d..7450be2 100644
--- a/OpenSim/Framework/OSChatMessage.cs
+++ b/OpenSim/Framework/OSChatMessage.cs
@@ -51,12 +51,11 @@ namespace OpenSim.Framework
51 protected object m_senderObject; 51 protected object m_senderObject;
52 protected ChatTypeEnum m_type; 52 protected ChatTypeEnum m_type;
53 protected UUID m_fromID; 53 protected UUID m_fromID;
54 protected UUID m_toID; 54 protected UUID m_destination = UUID.Zero;
55 55
56 public OSChatMessage() 56 public OSChatMessage()
57 { 57 {
58 m_position = new Vector3(); 58 m_position = new Vector3();
59 m_toID = UUID.Zero;
60 } 59 }
61 60
62 /// <summary> 61 /// <summary>
@@ -104,15 +103,6 @@ namespace OpenSim.Framework
104 set { m_from = value; } 103 set { m_from = value; }
105 } 104 }
106 105
107 /// <summary>
108 /// The name of the sender (needed for scripts)
109 /// </summary>
110 public string To
111 {
112 get { return m_from; }
113 set { m_from = value; }
114 }
115
116 #region IEventArgs Members 106 #region IEventArgs Members
117 107
118 /// TODO: Sender and SenderObject should just be Sender and of 108 /// TODO: Sender and SenderObject should just be Sender and of
@@ -142,13 +132,10 @@ namespace OpenSim.Framework
142 set { m_fromID = value; } 132 set { m_fromID = value; }
143 } 133 }
144 134
145 /// <summary> 135 public UUID Destination
146 /// The single recipient or all if not set.
147 /// </summary>
148 public UUID TargetUUID
149 { 136 {
150 get { return m_toID; } 137 get { return m_destination; }
151 set { m_toID = value; } 138 set { m_destination = value; }
152 } 139 }
153 140
154 /// <summary> 141 /// <summary>
diff --git a/OpenSim/Framework/ObjectChangeData.cs b/OpenSim/Framework/ObjectChangeData.cs
new file mode 100644
index 0000000..8d56291
--- /dev/null
+++ b/OpenSim/Framework/ObjectChangeData.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 OpenMetaverse;
29
30namespace OpenSim.Framework
31{
32 public enum ObjectChangeType : uint
33 {
34 // bits definitions
35 Position = 0x01,
36 Rotation = 0x02,
37 Scale = 0x04,
38 Group = 0x08,
39 UniformScale = 0x10,
40
41 // macros from above
42 // single prim
43 primP = 0x01,
44 primR = 0x02,
45 primPR = 0x03,
46 primS = 0x04,
47 primPS = 0x05,
48 primRS = 0x06,
49 primPSR = 0x07,
50
51 primUS = 0x14,
52 primPUS = 0x15,
53 primRUS = 0x16,
54 primPUSR = 0x17,
55
56 // group
57 groupP = 0x09,
58 groupR = 0x0A,
59 groupPR = 0x0B,
60 groupS = 0x0C,
61 groupPS = 0x0D,
62 groupRS = 0x0E,
63 groupPSR = 0x0F,
64
65 groupUS = 0x1C,
66 groupPUS = 0x1D,
67 groupRUS = 0x1E,
68 groupPUSR = 0x1F,
69
70 PRSmask = 0x07
71 }
72
73 public struct ObjectChangeData
74 {
75 public Quaternion rotation;
76 public Vector3 position;
77 public Vector3 scale;
78 public ObjectChangeType change;
79 }
80}
diff --git a/OpenSim/Framework/ParcelMediaCommandEnum.cs b/OpenSim/Framework/ParcelMediaCommandEnum.cs
index 93c41ec..e714382 100644
--- a/OpenSim/Framework/ParcelMediaCommandEnum.cs
+++ b/OpenSim/Framework/ParcelMediaCommandEnum.cs
@@ -27,7 +27,7 @@
27 27
28namespace OpenSim.Framework 28namespace OpenSim.Framework
29{ 29{
30 public enum ParcelMediaCommandEnum 30 public enum ParcelMediaCommandEnum : int
31 { 31 {
32 Stop = 0, 32 Stop = 0,
33 Pause = 1, 33 Pause = 1,
diff --git a/OpenSim/Framework/PermissionsUtil.cs b/OpenSim/Framework/PermissionsUtil.cs
index d785a78..5d3186d 100644
--- a/OpenSim/Framework/PermissionsUtil.cs
+++ b/OpenSim/Framework/PermissionsUtil.cs
@@ -72,8 +72,8 @@ namespace OpenSim.Framework
72 /// <param name="mainPerms">The permissions variable to modify.</param> 72 /// <param name="mainPerms">The permissions variable to modify.</param>
73 public static void ApplyFoldedPermissions(uint foldedPerms, ref uint mainPerms) 73 public static void ApplyFoldedPermissions(uint foldedPerms, ref uint mainPerms)
74 { 74 {
75 if ((foldedPerms & 7) == 0) 75// if ((foldedPerms & 7) == 0)
76 return; // assume that if the folded permissions are 0 then this means that they weren't actually recorded 76// return; // assume that if the folded permissions are 0 then this means that they weren't actually recorded
77 77
78 if ((foldedPerms & ((uint)PermissionMask.Copy >> 13)) == 0) 78 if ((foldedPerms & ((uint)PermissionMask.Copy >> 13)) == 0)
79 mainPerms &= ~(uint)PermissionMask.Copy; 79 mainPerms &= ~(uint)PermissionMask.Copy;
diff --git a/OpenSim/Framework/PluginLoader.cs b/OpenSim/Framework/PluginLoader.cs
index d12aa61..1e5e8bf 100644
--- a/OpenSim/Framework/PluginLoader.cs
+++ b/OpenSim/Framework/PluginLoader.cs
@@ -245,13 +245,22 @@ namespace OpenSim.Framework
245 // occasionally seems to corrupt its addin cache 245 // occasionally seems to corrupt its addin cache
246 // Hence, as a temporary solution we'll remove it before each startup 246 // Hence, as a temporary solution we'll remove it before each startup
247 247
248 string customDir = Environment.GetEnvironmentVariable ("MONO_ADDINS_REGISTRY");
249 string v0 = "addin-db-000";
250 string v1 = "addin-db-001";
251 if (customDir != null && customDir != String.Empty)
252 {
253 v0 = Path.Combine(customDir, v0);
254 v1 = Path.Combine(customDir, v1);
255 }
248 try 256 try
249 { 257 {
250 if (Directory.Exists(dir + "/addin-db-000")) 258 if (Directory.Exists(v0))
251 Directory.Delete(dir + "/addin-db-000", true); 259 Directory.Delete(v0, true);
260
261 if (Directory.Exists(v1))
262 Directory.Delete(v1, true);
252 263
253 if (Directory.Exists(dir + "/addin-db-001"))
254 Directory.Delete(dir + "/addin-db-001", true);
255 } 264 }
256 catch (IOException) 265 catch (IOException)
257 { 266 {
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index c8a5376..6a12a45 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -728,7 +728,12 @@ namespace OpenSim.Framework
728 return _lightColorR; 728 return _lightColorR;
729 } 729 }
730 set { 730 set {
731 _lightColorR = value; 731 if (value < 0)
732 _lightColorR = 0;
733 else if (value > 1.0f)
734 _lightColorR = 1.0f;
735 else
736 _lightColorR = value;
732 } 737 }
733 } 738 }
734 739
@@ -737,7 +742,12 @@ namespace OpenSim.Framework
737 return _lightColorG; 742 return _lightColorG;
738 } 743 }
739 set { 744 set {
740 _lightColorG = value; 745 if (value < 0)
746 _lightColorG = 0;
747 else if (value > 1.0f)
748 _lightColorG = 1.0f;
749 else
750 _lightColorG = value;
741 } 751 }
742 } 752 }
743 753
@@ -746,7 +756,12 @@ namespace OpenSim.Framework
746 return _lightColorB; 756 return _lightColorB;
747 } 757 }
748 set { 758 set {
749 _lightColorB = value; 759 if (value < 0)
760 _lightColorB = 0;
761 else if (value > 1.0f)
762 _lightColorB = 1.0f;
763 else
764 _lightColorB = value;
750 } 765 }
751 } 766 }
752 767
@@ -755,7 +770,12 @@ namespace OpenSim.Framework
755 return _lightColorA; 770 return _lightColorA;
756 } 771 }
757 set { 772 set {
758 _lightColorA = value; 773 if (value < 0)
774 _lightColorA = 0;
775 else if (value > 1.0f)
776 _lightColorA = 1.0f;
777 else
778 _lightColorA = value;
759 } 779 }
760 } 780 }
761 781
@@ -869,6 +889,11 @@ namespace OpenSim.Framework
869 889
870 public ulong GetMeshKey(Vector3 size, float lod) 890 public ulong GetMeshKey(Vector3 size, float lod)
871 { 891 {
892 return GetMeshKey(size, lod, false);
893 }
894
895 public ulong GetMeshKey(Vector3 size, float lod, bool convex)
896 {
872 ulong hash = 5381; 897 ulong hash = 5381;
873 898
874 hash = djb2(hash, this.PathCurve); 899 hash = djb2(hash, this.PathCurve);
@@ -914,6 +939,9 @@ namespace OpenSim.Framework
914 hash = djb2(hash, scaleBytes[i]); 939 hash = djb2(hash, scaleBytes[i]);
915 } 940 }
916 941
942 if(convex)
943 hash = djb2(hash, 0xa5);
944
917 return hash; 945 return hash;
918 } 946 }
919 947
@@ -1417,7 +1445,7 @@ namespace OpenSim.Framework
1417 prim.Textures = this.Textures; 1445 prim.Textures = this.Textures;
1418 1446
1419 prim.Properties = new Primitive.ObjectProperties(); 1447 prim.Properties = new Primitive.ObjectProperties();
1420 prim.Properties.Name = "Primitive"; 1448 prim.Properties.Name = "Object";
1421 prim.Properties.Description = ""; 1449 prim.Properties.Description = "";
1422 prim.Properties.CreatorID = UUID.Zero; 1450 prim.Properties.CreatorID = UUID.Zero;
1423 prim.Properties.GroupID = UUID.Zero; 1451 prim.Properties.GroupID = UUID.Zero;
diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs
index e7a7f7f..4f05f65 100644
--- a/OpenSim/Framework/PriorityQueue.cs
+++ b/OpenSim/Framework/PriorityQueue.cs
@@ -45,7 +45,8 @@ namespace OpenSim.Framework
45 /// <summary> 45 /// <summary>
46 /// Total number of queues (priorities) available 46 /// Total number of queues (priorities) available
47 /// </summary> 47 /// </summary>
48 public const uint NumberOfQueues = 12; 48
49 public const uint NumberOfQueues = 12; // includes immediate queues, m_queueCounts need to be set acording
49 50
50 /// <summary> 51 /// <summary>
51 /// Number of queuest (priorities) that are processed immediately 52 /// Number of queuest (priorities) that are processed immediately
@@ -60,7 +61,10 @@ namespace OpenSim.Framework
60 // each pass. weighted towards the higher priority queues 61 // each pass. weighted towards the higher priority queues
61 private uint m_nextQueue = 0; 62 private uint m_nextQueue = 0;
62 private uint m_countFromQueue = 0; 63 private uint m_countFromQueue = 0;
63 private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 }; 64 // first queues are imediate, so no counts
65// private uint[] m_queueCounts = { 0, 0, 8, 4, 4, 2, 2, 2, 2, 1, 1, 1 };
66 private uint[] m_queueCounts = {0, 0, 8, 8, 5, 4, 3, 2, 1, 1, 1, 1};
67 // this is ava, ava, attach, <10m, 20,40,80,160m,320,640,1280, +
64 68
65 // next request is a counter of the number of updates queued, it provides 69 // next request is a counter of the number of updates queued, it provides
66 // a total ordering on the updates coming through the queue and is more 70 // a total ordering on the updates coming through the queue and is more
@@ -130,6 +134,21 @@ namespace OpenSim.Framework
130 return true; 134 return true;
131 } 135 }
132 136
137
138 public void Remove(List<uint> ids)
139 {
140 LookupItem lookup;
141
142 foreach (uint localid in ids)
143 {
144 if (m_lookupTable.TryGetValue(localid, out lookup))
145 {
146 lookup.Heap.Remove(lookup.Handle);
147 m_lookupTable.Remove(localid);
148 }
149 }
150 }
151
133 /// <summary> 152 /// <summary>
134 /// Remove an item from one of the queues. Specifically, it removes the 153 /// Remove an item from one of the queues. Specifically, it removes the
135 /// oldest item from the next queue in order to provide fair access to 154 /// oldest item from the next queue in order to provide fair access to
@@ -137,7 +156,7 @@ namespace OpenSim.Framework
137 /// </summary> 156 /// </summary>
138 public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue) 157 public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
139 { 158 {
140 // If there is anything in priority queue 0, return it first no 159 // If there is anything in imediate queues, return it first no
141 // matter what else. Breaks fairness. But very useful. 160 // matter what else. Breaks fairness. But very useful.
142 for (int iq = 0; iq < NumberOfImmediateQueues; iq++) 161 for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
143 { 162 {
@@ -172,14 +191,13 @@ namespace OpenSim.Framework
172 } 191 }
173 192
174 // Find the next non-immediate queue with updates in it 193 // Find the next non-immediate queue with updates in it
175 for (int i = 0; i < NumberOfQueues; ++i) 194 for (uint i = NumberOfImmediateQueues; i < NumberOfQueues; ++i)
176 { 195 {
177 m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues); 196 m_nextQueue++;
178 m_countFromQueue = m_queueCounts[m_nextQueue]; 197 if(m_nextQueue >= NumberOfQueues)
198 m_nextQueue = NumberOfImmediateQueues;
179 199
180 // if this is one of the immediate queues, just skip it 200 m_countFromQueue = m_queueCounts[m_nextQueue];
181 if (m_nextQueue < NumberOfImmediateQueues)
182 continue;
183 201
184 if (m_heaps[m_nextQueue].Count > 0) 202 if (m_heaps[m_nextQueue].Count > 0)
185 { 203 {
@@ -189,7 +207,6 @@ namespace OpenSim.Framework
189 m_lookupTable.Remove(item.Value.Entity.LocalId); 207 m_lookupTable.Remove(item.Value.Entity.LocalId);
190 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); 208 timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
191 value = item.Value; 209 value = item.Value;
192
193 return true; 210 return true;
194 } 211 }
195 } 212 }
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 79fbd96..ac77352 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -40,6 +40,7 @@ using OpenMetaverse.StructuredData;
40 40
41namespace OpenSim.Framework 41namespace OpenSim.Framework
42{ 42{
43 [Serializable]
43 public class RegionLightShareData : ICloneable 44 public class RegionLightShareData : ICloneable
44 { 45 {
45 public bool valid = false; 46 public bool valid = false;
@@ -101,6 +102,11 @@ namespace OpenSim.Framework
101 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 102 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
102 private static readonly string LogHeader = "[REGION INFO]"; 103 private static readonly string LogHeader = "[REGION INFO]";
103 104
105
106 public bool commFailTF = false;
107 public ConfigurationMember configMember;
108 public string DataStore = String.Empty;
109
104 public string RegionFile = String.Empty; 110 public string RegionFile = String.Empty;
105 public bool isSandbox = false; 111 public bool isSandbox = false;
106 public bool Persistent = true; 112 public bool Persistent = true;
@@ -527,7 +533,7 @@ namespace OpenSim.Framework
527 return null; 533 return null;
528 } 534 }
529 535
530 private void SetExtraSetting(string key, string value) 536 public void SetExtraSetting(string key, string value)
531 { 537 {
532 string keylower = key.ToLower(); 538 string keylower = key.ToLower();
533 m_extraSettings[keylower] = value; 539 m_extraSettings[keylower] = value;
@@ -823,14 +829,16 @@ namespace OpenSim.Framework
823 string location = String.Format("{0},{1}", RegionLocX, RegionLocY); 829 string location = String.Format("{0},{1}", RegionLocX, RegionLocY);
824 config.Set("Location", location); 830 config.Set("Location", location);
825 831
826 if (RegionSizeX > 0) 832 if (DataStore != String.Empty)
827 config.Set("SizeX", RegionSizeX); 833 config.Set("Datastore", DataStore);
828 834
829 if (RegionSizeY > 0) 835 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
836 {
837 config.Set("SizeX", RegionSizeX);
830 config.Set("SizeY", RegionSizeY); 838 config.Set("SizeY", RegionSizeY);
831 839 // if (RegionSizeZ > 0)
832// if (RegionSizeZ > 0) 840 // config.Set("SizeZ", RegionSizeZ);
833// config.Set("SizeZ", RegionSizeZ); 841 }
834 842
835 config.Set("InternalAddress", m_internalEndPoint.Address.ToString()); 843 config.Set("InternalAddress", m_internalEndPoint.Address.ToString());
836 config.Set("InternalPort", m_internalEndPoint.Port); 844 config.Set("InternalPort", m_internalEndPoint.Port);
@@ -901,6 +909,232 @@ namespace OpenSim.Framework
901 throw new Exception("Invalid file type for region persistence."); 909 throw new Exception("Invalid file type for region persistence.");
902 } 910 }
903 911
912 public void loadConfigurationOptionsFromMe()
913 {
914 configMember.addConfigurationOption("sim_UUID", ConfigurationOption.ConfigurationTypes.TYPE_UUID_NULL_FREE,
915 "UUID of Region (Default is recommended, random UUID)",
916 RegionID.ToString(), true);
917 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
918 "Region Name", RegionName, true);
919
920 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
921 "Grid Location (X Axis)", RegionLocX.ToString(), true);
922 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
923 "Grid Location (Y Axis)", RegionLocY.ToString(), true);
924 configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
925 "Size of region in X dimension", RegionSizeX.ToString(), true);
926 configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
927 "Size of region in Y dimension", RegionSizeY.ToString(), true);
928 configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
929 "Size of region in Z dimension", RegionSizeZ.ToString(), true);
930
931 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
932 configMember.addConfigurationOption("internal_ip_address",
933 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
934 "Internal IP Address for incoming UDP client connections",
935 m_internalEndPoint.Address.ToString(),
936 true);
937 configMember.addConfigurationOption("internal_ip_port", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
938 "Internal IP Port for incoming UDP client connections",
939 m_internalEndPoint.Port.ToString(), true);
940 configMember.addConfigurationOption("allow_alternate_ports",
941 ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN,
942 "Allow sim to find alternate UDP ports when ports are in use?",
943 m_allow_alternate_ports.ToString(), true);
944 configMember.addConfigurationOption("external_host_name",
945 ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
946 "External Host Name", m_externalHostName, true);
947 configMember.addConfigurationOption("lastmap_uuid", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
948 "Last Map UUID", lastMapUUID.ToString(), true);
949 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
950 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
951
952 configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
953 "Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true);
954
955 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
956 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true);
957
958 configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
959 "Minimum size for nonphysical prims", m_physPrimMin.ToString(), true);
960
961 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
962 "Maximum size for physical prims", m_physPrimMax.ToString(), true);
963
964 configMember.addConfigurationOption("clamp_prim_size", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN,
965 "Clamp prims to max size", m_clampPrimSize.ToString(), true);
966
967 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
968 "Max objects this sim will hold", m_objectCapacity.ToString(), true);
969
970 configMember.addConfigurationOption("linkset_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
971 "Max prims an object will hold", m_linksetCapacity.ToString(), true);
972
973 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
974 "Max avatars this sim will hold",AgentCapacity.ToString(), true);
975
976 configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
977 "Scope ID for this region", ScopeID.ToString(), true);
978
979 configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING,
980 "Free form string describing the type of region", String.Empty, true);
981
982 configMember.addConfigurationOption("region_static_maptile", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
983 "UUID of a texture to use as the map for this region", m_maptileStaticUUID.ToString(), true);
984 }
985
986 public void loadConfigurationOptions()
987 {
988 configMember.addConfigurationOption("sim_UUID", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
989 "UUID of Region (Default is recommended, random UUID)",
990 UUID.Random().ToString(), true);
991 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
992 "Region Name", "OpenSim Test", false);
993
994 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
995 "Grid Location (X Axis)", "1000", false);
996 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
997 "Grid Location (Y Axis)", "1000", false);
998 configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
999 "Size of region in X dimension", Constants.RegionSize.ToString(), false);
1000 configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
1001 "Size of region in Y dimension", Constants.RegionSize.ToString(), false);
1002 configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
1003 "Size of region in Z dimension", Constants.RegionHeight.ToString(), false);
1004
1005 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
1006 configMember.addConfigurationOption("internal_ip_address",
1007 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
1008 "Internal IP Address for incoming UDP client connections", "0.0.0.0",
1009 false);
1010 configMember.addConfigurationOption("internal_ip_port", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
1011 "Internal IP Port for incoming UDP client connections",
1012 ConfigSettings.DefaultRegionHttpPort.ToString(), false);
1013 configMember.addConfigurationOption("allow_alternate_ports", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN,
1014 "Allow sim to find alternate UDP ports when ports are in use?",
1015 "false", true);
1016 configMember.addConfigurationOption("external_host_name",
1017 ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
1018 "External Host Name", "127.0.0.1", false);
1019 configMember.addConfigurationOption("lastmap_uuid", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
1020 "Last Map UUID", lastMapUUID.ToString(), true);
1021
1022 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
1023 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
1024
1025 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
1026 "Maximum size for nonphysical prims", "0", true);
1027
1028 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
1029 "Maximum size for physical prims", "0", true);
1030
1031 configMember.addConfigurationOption("clamp_prim_size", ConfigurationOption.ConfigurationTypes.TYPE_BOOLEAN,
1032 "Clamp prims to max size", "false", true);
1033
1034 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
1035 "Max objects this sim will hold", "15000", true);
1036
1037 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
1038 "Max avatars this sim will hold", "100", true);
1039
1040 configMember.addConfigurationOption("scope_id", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
1041 "Scope ID for this region", UUID.Zero.ToString(), true);
1042
1043 configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING,
1044 "Region Type", String.Empty, true);
1045
1046 configMember.addConfigurationOption("region_static_maptile", ConfigurationOption.ConfigurationTypes.TYPE_UUID,
1047 "UUID of a texture to use as the map for this region", String.Empty, true);
1048 }
1049
1050 public bool handleIncomingConfiguration(string configuration_key, object configuration_result)
1051 {
1052 switch (configuration_key)
1053 {
1054 case "sim_UUID":
1055 RegionID = (UUID) configuration_result;
1056 originRegionID = (UUID) configuration_result;
1057 break;
1058 case "sim_name":
1059 RegionName = (string) configuration_result;
1060 break;
1061 case "sim_location_x":
1062 RegionLocX = (uint) configuration_result;
1063 break;
1064 case "sim_location_y":
1065 RegionLocY = (uint) configuration_result;
1066 break;
1067 case "sim_size_x":
1068 RegionSizeX = (uint) configuration_result;
1069 break;
1070 case "sim_size_y":
1071 RegionSizeY = (uint) configuration_result;
1072 break;
1073 case "sim_size_z":
1074 RegionSizeZ = (uint) configuration_result;
1075 break;
1076 case "datastore":
1077 DataStore = (string) configuration_result;
1078 break;
1079 case "internal_ip_address":
1080 IPAddress address = (IPAddress) configuration_result;
1081 m_internalEndPoint = new IPEndPoint(address, 0);
1082 break;
1083 case "internal_ip_port":
1084 m_internalEndPoint.Port = (int) configuration_result;
1085 break;
1086 case "allow_alternate_ports":
1087 m_allow_alternate_ports = (bool) configuration_result;
1088 break;
1089 case "external_host_name":
1090 if ((string) configuration_result != "SYSTEMIP")
1091 {
1092 m_externalHostName = (string) configuration_result;
1093 }
1094 else
1095 {
1096 m_externalHostName = Util.GetLocalHost().ToString();
1097 }
1098 break;
1099 case "lastmap_uuid":
1100 lastMapUUID = (UUID)configuration_result;
1101 break;
1102 case "lastmap_refresh":
1103 lastMapRefresh = (string)configuration_result;
1104 break;
1105 case "nonphysical_prim_max":
1106 m_nonphysPrimMax = (int)configuration_result;
1107 break;
1108 case "physical_prim_max":
1109 m_physPrimMax = (int)configuration_result;
1110 break;
1111 case "clamp_prim_size":
1112 m_clampPrimSize = (bool)configuration_result;
1113 break;
1114 case "object_capacity":
1115 m_objectCapacity = (int)configuration_result;
1116 break;
1117 case "linkset_capacity":
1118 m_linksetCapacity = (int)configuration_result;
1119 break;
1120 case "agent_capacity":
1121 AgentCapacity = (int)configuration_result;
1122 break;
1123 case "scope_id":
1124 ScopeID = (UUID)configuration_result;
1125 break;
1126 case "region_type":
1127 m_regionType = (string)configuration_result;
1128 break;
1129 case "region_static_maptile":
1130 m_maptileStaticUUID = (UUID)configuration_result;
1131 break;
1132 }
1133
1134 return true;
1135 }
1136
1137
904 public void SaveLastMapUUID(UUID mapUUID) 1138 public void SaveLastMapUUID(UUID mapUUID)
905 { 1139 {
906 lastMapUUID = mapUUID; 1140 lastMapUUID = mapUUID;
@@ -1004,5 +1238,28 @@ namespace OpenSim.Framework
1004 regionInfo.ServerURI = serverURI; 1238 regionInfo.ServerURI = serverURI;
1005 return regionInfo; 1239 return regionInfo;
1006 } 1240 }
1241
1242 public int getInternalEndPointPort()
1243 {
1244 return m_internalEndPoint.Port;
1245 }
1246
1247 public Dictionary<string, object> ToKeyValuePairs()
1248 {
1249 Dictionary<string, object> kvp = new Dictionary<string, object>();
1250 kvp["uuid"] = RegionID.ToString();
1251 kvp["locX"] = RegionLocX.ToString();
1252 kvp["locY"] = RegionLocY.ToString();
1253 kvp["external_ip_address"] = ExternalEndPoint.Address.ToString();
1254 kvp["external_port"] = ExternalEndPoint.Port.ToString();
1255 kvp["external_host_name"] = ExternalHostName;
1256 kvp["http_port"] = HttpPort.ToString();
1257 kvp["internal_ip_address"] = InternalEndPoint.Address.ToString();
1258 kvp["internal_port"] = InternalEndPoint.Port.ToString();
1259 kvp["alternate_ports"] = m_allow_alternate_ports.ToString();
1260 kvp["server_uri"] = ServerURI;
1261
1262 return kvp;
1263 }
1007 } 1264 }
1008} 1265}
diff --git a/OpenSim/Framework/RegionSettings.cs b/OpenSim/Framework/RegionSettings.cs
index a895c40..dec01ea 100644
--- a/OpenSim/Framework/RegionSettings.cs
+++ b/OpenSim/Framework/RegionSettings.cs
@@ -482,6 +482,28 @@ namespace OpenSim.Framework
482 set { m_LoadedCreationID = value; } 482 set { m_LoadedCreationID = value; }
483 } 483 }
484 484
485 private bool m_GodBlockSearch = false;
486 public bool GodBlockSearch
487 {
488 get { return m_GodBlockSearch; }
489 set { m_GodBlockSearch = value; }
490 }
491
492 private bool m_Casino = false;
493 public bool Casino
494 {
495 get { return m_Casino; }
496 set { m_Casino = value; }
497 }
498
499 // Telehub support
500 private bool m_TelehubEnabled = false;
501 public bool HasTelehub
502 {
503 get { return m_TelehubEnabled; }
504 set { m_TelehubEnabled = value; }
505 }
506
485 /// <summary> 507 /// <summary>
486 /// Connected Telehub object 508 /// Connected Telehub object
487 /// </summary> 509 /// </summary>
@@ -520,4 +542,4 @@ namespace OpenSim.Framework
520 l_SpawnPoints.Clear(); 542 l_SpawnPoints.Clear();
521 } 543 }
522 } 544 }
523} \ No newline at end of file 545}
diff --git a/OpenSim/Framework/RestClient.cs b/OpenSim/Framework/RestClient.cs
index 7080ca5..ca19392 100644
--- a/OpenSim/Framework/RestClient.cs
+++ b/OpenSim/Framework/RestClient.cs
@@ -388,10 +388,10 @@ namespace OpenSim.Framework
388 m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e); 388 m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e);
389 } 389 }
390 } 390 }
391
392 return null; 391 return null;
393 } 392 }
394 393
394
395 if (_asyncException != null) 395 if (_asyncException != null)
396 throw _asyncException; 396 throw _asyncException;
397 397
@@ -413,7 +413,7 @@ namespace OpenSim.Framework
413 _request = (HttpWebRequest) WebRequest.Create(buildUri()); 413 _request = (HttpWebRequest) WebRequest.Create(buildUri());
414 _request.KeepAlive = false; 414 _request.KeepAlive = false;
415 _request.ContentType = "application/xml"; 415 _request.ContentType = "application/xml";
416 _request.Timeout = 900000; 416 _request.Timeout = 90000;
417 _request.Method = RequestMethod; 417 _request.Method = RequestMethod;
418 _asyncException = null; 418 _asyncException = null;
419 _request.ContentLength = src.Length; 419 _request.ContentLength = src.Length;
@@ -428,14 +428,18 @@ namespace OpenSim.Framework
428 if (WebUtil.DebugLevel >= 5) 428 if (WebUtil.DebugLevel >= 5)
429 WebUtil.LogOutgoingDetail(string.Format("SEND {0}: ", reqnum), src); 429 WebUtil.LogOutgoingDetail(string.Format("SEND {0}: ", reqnum), src);
430 430
431 Stream dst = _request.GetRequestStream(); 431 using (Stream dst = _request.GetRequestStream())
432
433 byte[] buf = new byte[1024];
434 int length = src.Read(buf, 0, 1024);
435 while (length > 0)
436 { 432 {
437 dst.Write(buf, 0, length); 433 m_log.Info("[REST]: GetRequestStream is ok");
438 length = src.Read(buf, 0, 1024); 434
435 byte[] buf = new byte[1024];
436 int length = src.Read(buf, 0, 1024);
437 m_log.Info("[REST]: First Read is ok");
438 while (length > 0)
439 {
440 dst.Write(buf, 0, length);
441 length = src.Read(buf, 0, 1024);
442 }
439 } 443 }
440 444
441 try 445 try
@@ -468,7 +472,8 @@ namespace OpenSim.Framework
468 } 472 }
469 } 473 }
470 474
471 _response.Close(); 475 if (_response != null)
476 _response.Close();
472 477
473// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); 478// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
474 479
@@ -673,4 +678,4 @@ namespace OpenSim.Framework
673 } 678 }
674 } 679 }
675 680
676} \ No newline at end of file 681}
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 828a852..3426d10 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -65,6 +65,7 @@ namespace OpenSim.Framework.Servers
65 /// This will control a periodic log printout of the current 'show stats' (if they are active) for this 65 /// This will control a periodic log printout of the current 'show stats' (if they are active) for this
66 /// server. 66 /// server.
67 /// </summary> 67 /// </summary>
68
68 private int m_periodDiagnosticTimerMS = 60 * 60 * 1000; 69 private int m_periodDiagnosticTimerMS = 60 * 60 * 1000;
69 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); 70 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000);
70 71
@@ -83,7 +84,6 @@ namespace OpenSim.Framework.Servers
83 { 84 {
84 // Random uuid for private data 85 // Random uuid for private data
85 m_osSecret = UUID.Random().ToString(); 86 m_osSecret = UUID.Random().ToString();
86
87 } 87 }
88 88
89 /// <summary> 89 /// <summary>
@@ -146,14 +146,24 @@ namespace OpenSim.Framework.Servers
146 /// Performs initialisation of the scene, such as loading configuration from disk. 146 /// Performs initialisation of the scene, such as loading configuration from disk.
147 /// </summary> 147 /// </summary>
148 public virtual void Startup() 148 public virtual void Startup()
149 { 149 {
150 m_log.Info("[STARTUP]: Beginning startup processing");
151
152 m_log.Info("[STARTUP]: version: " + m_version + Environment.NewLine);
153 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
154 // the clr version number doesn't match the project version number under Mono.
155 //m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine);
156 m_log.InfoFormat(
157 "[STARTUP]: Operating system version: {0}, .NET platform {1}, {2}-bit\n",
158 Environment.OSVersion, Environment.OSVersion.Platform, Util.Is64BitProcess() ? "64" : "32");
159
150 StartupSpecific(); 160 StartupSpecific();
151 161
152 TimeSpan timeTaken = DateTime.Now - m_startuptime; 162 TimeSpan timeTaken = DateTime.Now - m_startuptime;
153 163
154 MainConsole.Instance.OutputFormat( 164// MainConsole.Instance.OutputFormat(
155 "PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED. Non-script portion of startup took {0}m {1}s.", 165// "PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED. Non-script portion of startup took {0}m {1}s.",
156 timeTaken.Minutes, timeTaken.Seconds); 166// timeTaken.Minutes, timeTaken.Seconds);
157 } 167 }
158 168
159 public string osSecret 169 public string osSecret
@@ -175,4 +185,4 @@ namespace OpenSim.Framework.Servers
175 } 185 }
176 } 186 }
177 } 187 }
178} \ No newline at end of file 188}
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index f252bd5..cd14212 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -403,6 +403,7 @@ namespace OpenSim.Framework.Servers.HttpServer
403 StreamReader reader = new StreamReader(requestStream, encoding); 403 StreamReader reader = new StreamReader(requestStream, encoding);
404 404
405 string requestBody = reader.ReadToEnd(); 405 string requestBody = reader.ReadToEnd();
406 reader.Close();
406 407
407 Hashtable keysvals = new Hashtable(); 408 Hashtable keysvals = new Hashtable();
408 Hashtable headervals = new Hashtable(); 409 Hashtable headervals = new Hashtable();
@@ -460,7 +461,7 @@ namespace OpenSim.Framework.Servers.HttpServer
460 } 461 }
461 462
462 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 463 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
463 resp.ReuseContext = true; 464 resp.ReuseContext = false;
464 HandleRequest(req, resp); 465 HandleRequest(req, resp);
465 466
466 // !!!HACK ALERT!!! 467 // !!!HACK ALERT!!!
@@ -759,7 +760,7 @@ namespace OpenSim.Framework.Servers.HttpServer
759 // Every month or so this will wrap and give bad numbers, not really a problem 760 // Every month or so this will wrap and give bad numbers, not really a problem
760 // since its just for reporting 761 // since its just for reporting
761 int tickdiff = requestEndTick - requestStartTick; 762 int tickdiff = requestEndTick - requestStartTick;
762 if (tickdiff > 3000 && requestHandler != null && requestHandler.Name != "GetTexture") 763 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
763 { 764 {
764 m_log.InfoFormat( 765 m_log.InfoFormat(
765 "[LOGHTTP] Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", 766 "[LOGHTTP] Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
@@ -1024,6 +1025,19 @@ namespace OpenSim.Framework.Servers.HttpServer
1024 string responseString = String.Empty; 1025 string responseString = String.Empty;
1025 XmlRpcRequest xmlRprcRequest = null; 1026 XmlRpcRequest xmlRprcRequest = null;
1026 1027
1028 bool gridproxy = false;
1029 if (requestBody.Contains("encoding=\"utf-8"))
1030 {
1031 int channelindx = -1;
1032 int optionsindx = requestBody.IndexOf(">options<");
1033 if(optionsindx >0)
1034 {
1035 channelindx = requestBody.IndexOf(">channel<");
1036 if (optionsindx < channelindx)
1037 gridproxy = true;
1038 }
1039 }
1040
1027 try 1041 try
1028 { 1042 {
1029 xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody); 1043 xmlRprcRequest = (XmlRpcRequest) (new XmlRpcRequestDeserializer()).Deserialize(requestBody);
@@ -1081,6 +1095,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1081 } 1095 }
1082 xmlRprcRequest.Params.Add(request.Headers.Get(xff)); // Param[3] 1096 xmlRprcRequest.Params.Add(request.Headers.Get(xff)); // Param[3]
1083 1097
1098 if (gridproxy)
1099 xmlRprcRequest.Params.Add("gridproxy"); // Param[4]
1084 try 1100 try
1085 { 1101 {
1086 xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint); 1102 xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint);
@@ -1254,7 +1270,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1254 requestStream.Close(); 1270 requestStream.Close();
1255 1271
1256 //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody); 1272 //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody);
1257 response.KeepAlive = true; 1273 // response.KeepAlive = true;
1274 response.KeepAlive = false;
1258 1275
1259 OSD llsdRequest = null; 1276 OSD llsdRequest = null;
1260 OSD llsdResponse = null; 1277 OSD llsdResponse = null;
@@ -1732,10 +1749,40 @@ namespace OpenSim.Framework.Servers.HttpServer
1732 1749
1733 internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response) 1750 internal byte[] DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response)
1734 { 1751 {
1735 //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response"); 1752 int responsecode;
1736 int responsecode = (int)responsedata["int_response_code"]; 1753 string responseString = String.Empty;
1737 string responseString = (string)responsedata["str_response_string"]; 1754 byte[] responseData = null;
1738 string contentType = (string)responsedata["content_type"]; 1755 string contentType;
1756
1757 if (responsedata == null)
1758 {
1759 responsecode = 500;
1760 responseString = "No response could be obtained";
1761 contentType = "text/plain";
1762 responsedata = new Hashtable();
1763 }
1764 else
1765 {
1766 try
1767 {
1768 //m_log.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
1769 responsecode = (int)responsedata["int_response_code"];
1770 if (responsedata["bin_response_data"] != null)
1771 responseData = (byte[])responsedata["bin_response_data"];
1772 else
1773 responseString = (string)responsedata["str_response_string"];
1774 contentType = (string)responsedata["content_type"];
1775 if (responseString == null)
1776 responseString = String.Empty;
1777 }
1778 catch
1779 {
1780 responsecode = 500;
1781 responseString = "No response could be obtained";
1782 contentType = "text/plain";
1783 responsedata = new Hashtable();
1784 }
1785 }
1739 1786
1740 if (responsedata.ContainsKey("error_status_text")) 1787 if (responsedata.ContainsKey("error_status_text"))
1741 { 1788 {
@@ -1745,16 +1792,19 @@ namespace OpenSim.Framework.Servers.HttpServer
1745 { 1792 {
1746 response.ProtocolVersion = (string)responsedata["http_protocol_version"]; 1793 response.ProtocolVersion = (string)responsedata["http_protocol_version"];
1747 } 1794 }
1748 1795/*
1749 if (responsedata.ContainsKey("keepalive")) 1796 if (responsedata.ContainsKey("keepalive"))
1750 { 1797 {
1751 bool keepalive = (bool)responsedata["keepalive"]; 1798 bool keepalive = (bool)responsedata["keepalive"];
1752 response.KeepAlive = keepalive; 1799 response.KeepAlive = keepalive;
1753
1754 } 1800 }
1755 1801
1756 if (responsedata.ContainsKey("reusecontext")) 1802 if (responsedata.ContainsKey("reusecontext"))
1757 response.ReuseContext = (bool) responsedata["reusecontext"]; 1803 response.ReuseContext = (bool) responsedata["reusecontext"];
1804*/
1805 // disable this things
1806 response.KeepAlive = false;
1807 response.ReuseContext = false;
1758 1808
1759 // Cross-Origin Resource Sharing with simple requests 1809 // Cross-Origin Resource Sharing with simple requests
1760 if (responsedata.ContainsKey("access_control_allow_origin")) 1810 if (responsedata.ContainsKey("access_control_allow_origin"))
@@ -1768,8 +1818,11 @@ namespace OpenSim.Framework.Servers.HttpServer
1768 contentType = "text/html"; 1818 contentType = "text/html";
1769 } 1819 }
1770 1820
1821
1822
1771 // The client ignores anything but 200 here for web login, so ensure that this is 200 for that 1823 // The client ignores anything but 200 here for web login, so ensure that this is 200 for that
1772 1824
1825
1773 response.StatusCode = responsecode; 1826 response.StatusCode = responsecode;
1774 1827
1775 if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently) 1828 if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently)
@@ -1780,25 +1833,40 @@ namespace OpenSim.Framework.Servers.HttpServer
1780 1833
1781 response.AddHeader("Content-Type", contentType); 1834 response.AddHeader("Content-Type", contentType);
1782 1835
1836 if (responsedata.ContainsKey("headers"))
1837 {
1838 Hashtable headerdata = (Hashtable)responsedata["headers"];
1839
1840 foreach (string header in headerdata.Keys)
1841 response.AddHeader(header, (string)headerdata[header]);
1842 }
1843
1783 byte[] buffer; 1844 byte[] buffer;
1784 1845
1785 if (!(contentType.Contains("image") 1846 if (responseData != null)
1786 || contentType.Contains("x-shockwave-flash")
1787 || contentType.Contains("application/x-oar")
1788 || contentType.Contains("application/vnd.ll.mesh")))
1789 { 1847 {
1790 // Text 1848 buffer = responseData;
1791 buffer = Encoding.UTF8.GetBytes(responseString);
1792 } 1849 }
1793 else 1850 else
1794 { 1851 {
1795 // Binary! 1852 if (!(contentType.Contains("image")
1796 buffer = Convert.FromBase64String(responseString); 1853 || contentType.Contains("x-shockwave-flash")
1797 } 1854 || contentType.Contains("application/x-oar")
1855 || contentType.Contains("application/vnd.ll.mesh")))
1856 {
1857 // Text
1858 buffer = Encoding.UTF8.GetBytes(responseString);
1859 }
1860 else
1861 {
1862 // Binary!
1863 buffer = Convert.FromBase64String(responseString);
1864 }
1798 1865
1799 response.SendChunked = false; 1866 response.SendChunked = false;
1800 response.ContentLength64 = buffer.Length; 1867 response.ContentLength64 = buffer.Length;
1801 response.ContentEncoding = Encoding.UTF8; 1868 response.ContentEncoding = Encoding.UTF8;
1869 }
1802 1870
1803 return buffer; 1871 return buffer;
1804 } 1872 }
@@ -1886,6 +1954,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1886 m_httpListener2.Start(64); 1954 m_httpListener2.Start(64);
1887 1955
1888 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1956 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1957
1889 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000); 1958 PollServiceRequestManager = new PollServiceRequestManager(this, performPollResponsesAsync, 3, 25000);
1890 PollServiceRequestManager.Start(); 1959 PollServiceRequestManager.Start();
1891 1960
@@ -1937,7 +2006,9 @@ namespace OpenSim.Framework.Servers.HttpServer
1937 2006
1938 public void httpServerException(object source, Exception exception) 2007 public void httpServerException(object source, Exception exception)
1939 { 2008 {
1940 m_log.Error(String.Format("[BASE HTTP SERVER]: {0} had an exception: {1} ", source.ToString(), exception.Message), exception); 2009 if (source.ToString() == "HttpServer.HttpListener" && exception.ToString().StartsWith("Mono.Security.Protocol.Tls.TlsException"))
2010 return;
2011 m_log.ErrorFormat("[BASE HTTP SERVER]: {0} had an exception {1}", source.ToString(), exception.ToString());
1941 /* 2012 /*
1942 if (HTTPDRunning)// && NotSocketErrors > 5) 2013 if (HTTPDRunning)// && NotSocketErrors > 5)
1943 { 2014 {
@@ -1984,6 +2055,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1984 2055
1985 public void RemoveHTTPHandler(string httpMethod, string path) 2056 public void RemoveHTTPHandler(string httpMethod, string path)
1986 { 2057 {
2058 if (path == null) return; // Caps module isn't loaded, tries to remove handler where path = null
1987 lock (m_HTTPHandlers) 2059 lock (m_HTTPHandlers)
1988 { 2060 {
1989 if (httpMethod != null && httpMethod.Length == 0) 2061 if (httpMethod != null && httpMethod.Length == 0)
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
index 89fb5d4..17e9dc2 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpResponse.cs
@@ -148,6 +148,7 @@ namespace OpenSim.Framework.Servers.HttpServer
148 _httpResponse.Connection = ConnectionType.Close; 148 _httpResponse.Connection = ConnectionType.Close;
149 _httpResponse.KeepAlive = 0; 149 _httpResponse.KeepAlive = 0;
150 } 150 }
151
151 else 152 else
152 { 153 {
153 _httpResponse.Connection = ConnectionType.KeepAlive; 154 _httpResponse.Connection = ConnectionType.KeepAlive;
@@ -320,6 +321,11 @@ namespace OpenSim.Framework.Servers.HttpServer
320 public void Send() 321 public void Send()
321 { 322 {
322 _httpResponse.Body.Flush(); 323 _httpResponse.Body.Flush();
324
325 // disable this till they are safe to use
326 _httpResponse.Connection = ConnectionType.Close;
327 _httpResponse.Chunked = false;
328
323 _httpResponse.Send(); 329 _httpResponse.Send();
324 } 330 }
325 331
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index 9477100..3fd3bf7 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -52,7 +52,9 @@ namespace OpenSim.Framework.Servers.HttpServer
52 { 52 {
53 LongPoll = 0, 53 LongPoll = 0,
54 LslHttp = 1, 54 LslHttp = 1,
55 Inventory = 2 55 Inventory = 2,
56 Texture = 3,
57 Mesh = 4
56 } 58 }
57 59
58 public string Url { get; set; } 60 public string Url { get; set; }
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
index caf0e98..49cd110 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using System.Text; 32using System.Text;
32using HttpServer; 33using HttpServer;
@@ -44,6 +45,24 @@ namespace OpenSim.Framework.Servers.HttpServer
44 public readonly IHttpRequest Request; 45 public readonly IHttpRequest Request;
45 public readonly int RequestTime; 46 public readonly int RequestTime;
46 public readonly UUID RequestID; 47 public readonly UUID RequestID;
48 public int contextHash;
49
50 private void GenContextHash()
51 {
52 Random rnd = new Random();
53 contextHash = 0;
54 if (Request.Headers["remote_addr"] != null)
55 contextHash = (Request.Headers["remote_addr"]).GetHashCode() << 16;
56 else
57 contextHash = rnd.Next() << 16;
58 if (Request.Headers["remote_port"] != null)
59 {
60 string[] strPorts = Request.Headers["remote_port"].Split(new char[] { ',' });
61 contextHash += Int32.Parse(strPorts[0]);
62 }
63 else
64 contextHash += rnd.Next() & 0xffff;
65 }
47 66
48 public PollServiceHttpRequest( 67 public PollServiceHttpRequest(
49 PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest) 68 PollServiceEventArgs pPollServiceArgs, IHttpClientContext pHttpContext, IHttpRequest pRequest)
@@ -53,6 +72,7 @@ namespace OpenSim.Framework.Servers.HttpServer
53 Request = pRequest; 72 Request = pRequest;
54 RequestTime = System.Environment.TickCount; 73 RequestTime = System.Environment.TickCount;
55 RequestID = UUID.Random(); 74 RequestID = UUID.Random();
75 GenContextHash();
56 } 76 }
57 77
58 internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata) 78 internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
@@ -65,6 +85,7 @@ namespace OpenSim.Framework.Servers.HttpServer
65 response.SendChunked = false; 85 response.SendChunked = false;
66 response.ContentLength64 = buffer.Length; 86 response.ContentLength64 = buffer.Length;
67 response.ContentEncoding = Encoding.UTF8; 87 response.ContentEncoding = Encoding.UTF8;
88 response.ReuseContext = false;
68 89
69 try 90 try
70 { 91 {
@@ -93,5 +114,44 @@ namespace OpenSim.Framework.Servers.HttpServer
93 PollServiceArgs.RequestsHandled++; 114 PollServiceArgs.RequestsHandled++;
94 } 115 }
95 } 116 }
117
118 internal void DoHTTPstop(BaseHttpServer server)
119 {
120 OSHttpResponse response
121 = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
122
123 response.SendChunked = false;
124 response.ContentLength64 = 0;
125 response.ContentEncoding = Encoding.UTF8;
126 response.ReuseContext = false;
127 response.KeepAlive = false;
128 response.SendChunked = false;
129 response.StatusCode = 503;
130
131 try
132 {
133 response.OutputStream.Flush();
134 response.Send();
135 }
136 catch (Exception e)
137 {
138 }
139 }
140 }
141
142 class PollServiceHttpRequestComparer : IEqualityComparer<PollServiceHttpRequest>
143 {
144 public bool Equals(PollServiceHttpRequest b1, PollServiceHttpRequest b2)
145 {
146 if (b1.contextHash != b2.contextHash)
147 return false;
148 bool b = Object.ReferenceEquals(b1.HttpContext, b2.HttpContext);
149 return b;
150 }
151
152 public int GetHashCode(PollServiceHttpRequest b2)
153 {
154 return (int)b2.contextHash;
155 }
96 } 156 }
97} \ No newline at end of file 157} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 28bba70..0e4323a 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -44,183 +44,199 @@ namespace OpenSim.Framework.Servers.HttpServer
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 /// <summary>
48 /// Is the poll service request manager running?
49 /// </summary>
50 /// <remarks>
51 /// Can be running either synchronously or asynchronously
52 /// </remarks>
53 public bool IsRunning { get; private set; }
54
55 /// <summary>
56 /// Is the poll service performing responses asynchronously (with its own threads) or synchronously (via
57 /// external calls)?
58 /// </summary>
59 public bool PerformResponsesAsync { get; private set; }
60
61 /// <summary>
62 /// Number of responses actually processed and sent to viewer (or aborted due to error).
63 /// </summary>
64 public int ResponsesProcessed { get; private set; }
65
66 private readonly BaseHttpServer m_server; 47 private readonly BaseHttpServer m_server;
67 48
49 private Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>> m_bycontext;
68 private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>(); 50 private BlockingQueue<PollServiceHttpRequest> m_requests = new BlockingQueue<PollServiceHttpRequest>();
69 private static List<PollServiceHttpRequest> m_longPollRequests = new List<PollServiceHttpRequest>(); 51 private static Queue<PollServiceHttpRequest> m_slowRequests = new Queue<PollServiceHttpRequest>();
52 private static Queue<PollServiceHttpRequest> m_retryRequests = new Queue<PollServiceHttpRequest>();
70 53
71 private uint m_WorkerThreadCount = 0; 54 private uint m_WorkerThreadCount = 0;
72 private Thread[] m_workerThreads; 55 private Thread[] m_workerThreads;
56 private Thread m_retrysThread;
57
58 private bool m_running = false;
59 private int slowCount = 0;
73 60
74 private SmartThreadPool m_threadPool = new SmartThreadPool(20000, 12, 2); 61 private SmartThreadPool m_threadPool;
75 62
76// private int m_timeout = 1000; // increase timeout 250; now use the event one
77 63
78 public PollServiceRequestManager( 64 public PollServiceRequestManager(
79 BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout) 65 BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout)
80 { 66 {
81 m_server = pSrv; 67 m_server = pSrv;
82 PerformResponsesAsync = performResponsesAsync;
83 m_WorkerThreadCount = pWorkerThreadCount; 68 m_WorkerThreadCount = pWorkerThreadCount;
84 m_workerThreads = new Thread[m_WorkerThreadCount]; 69 m_workerThreads = new Thread[m_WorkerThreadCount];
85 70
86 StatsManager.RegisterStat( 71 PollServiceHttpRequestComparer preqCp = new PollServiceHttpRequestComparer();
87 new Stat( 72 m_bycontext = new Dictionary<PollServiceHttpRequest, Queue<PollServiceHttpRequest>>(preqCp);
88 "QueuedPollResponses", 73
89 "Number of poll responses queued for processing.", 74 STPStartInfo startInfo = new STPStartInfo();
90 "", 75 startInfo.IdleTimeout = 30000;
91 "", 76 startInfo.MaxWorkerThreads = 15;
92 "httpserver", 77 startInfo.MinWorkerThreads = 1;
93 m_server.Port.ToString(), 78 startInfo.ThreadPriority = ThreadPriority.Normal;
94 StatType.Pull, 79 startInfo.StartSuspended = true;
95 MeasuresOfInterest.AverageChangeOverTime, 80 startInfo.ThreadPoolName = "PoolService";
96 stat => stat.Value = m_requests.Count(), 81
97 StatVerbosity.Debug)); 82 m_threadPool = new SmartThreadPool(startInfo);
98 83
99 StatsManager.RegisterStat(
100 new Stat(
101 "ProcessedPollResponses",
102 "Number of poll responses processed.",
103 "",
104 "",
105 "httpserver",
106 m_server.Port.ToString(),
107 StatType.Pull,
108 MeasuresOfInterest.AverageChangeOverTime,
109 stat => stat.Value = ResponsesProcessed,
110 StatVerbosity.Debug));
111 } 84 }
112 85
113 public void Start() 86 public void Start()
114 { 87 {
115 IsRunning = true; 88 m_running = true;
116 89 m_threadPool.Start();
117 if (PerformResponsesAsync) 90 //startup worker threads
91 for (uint i = 0; i < m_WorkerThreadCount; i++)
118 { 92 {
119 //startup worker threads 93 m_workerThreads[i]
120 for (uint i = 0; i < m_WorkerThreadCount; i++) 94 = WorkManager.StartThread(
121 { 95 PoolWorkerJob,
122 m_workerThreads[i] 96 string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port),
123 = WorkManager.StartThread( 97 ThreadPriority.Normal,
124 PoolWorkerJob, 98 false,
125 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port), 99 false,
126 ThreadPriority.Normal, 100 null,
127 false, 101 int.MaxValue);
128 false,
129 null,
130 int.MaxValue);
131 }
132
133 WorkManager.StartThread(
134 this.CheckLongPollThreads,
135 string.Format("LongPollServiceWatcherThread:{0}", m_server.Port),
136 ThreadPriority.Normal,
137 false,
138 true,
139 null,
140 1000 * 60 * 10);
141 } 102 }
103
104 m_retrysThread = WorkManager.StartThread(
105 this.CheckRetries,
106 string.Format("PollServiceWatcherThread:{0}", m_server.Port),
107 ThreadPriority.Normal,
108 false,
109 true,
110 null,
111 1000 * 60 * 10);
112
113
142 } 114 }
143 115
144 private void ReQueueEvent(PollServiceHttpRequest req) 116 private void ReQueueEvent(PollServiceHttpRequest req)
145 { 117 {
146 if (IsRunning) 118 if (m_running)
147 { 119 {
148 // delay the enqueueing for 100ms. There's no need to have the event 120 lock (m_retryRequests)
149 // actively on the queue 121 m_retryRequests.Enqueue(req);
150 Timer t = new Timer(self => {
151 ((Timer)self).Dispose();
152 m_requests.Enqueue(req);
153 });
154
155 t.Change(100, Timeout.Infinite);
156
157 } 122 }
158 } 123 }
159 124
160 public void Enqueue(PollServiceHttpRequest req) 125 public void Enqueue(PollServiceHttpRequest req)
161 { 126 {
162 if (IsRunning) 127 lock (m_bycontext)
163 { 128 {
164 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) 129 Queue<PollServiceHttpRequest> ctxQeueue;
130 if (m_bycontext.TryGetValue(req, out ctxQeueue))
165 { 131 {
166 lock (m_longPollRequests) 132 ctxQeueue.Enqueue(req);
167 m_longPollRequests.Add(req);
168 } 133 }
169 else 134 else
170 m_requests.Enqueue(req); 135 {
136 ctxQeueue = new Queue<PollServiceHttpRequest>();
137 m_bycontext[req] = ctxQeueue;
138 EnqueueInt(req);
139 }
171 } 140 }
172 } 141 }
173 142
174 private void CheckLongPollThreads() 143 public void byContextDequeue(PollServiceHttpRequest req)
175 { 144 {
176 // The only purpose of this thread is to check the EQs for events. 145 Queue<PollServiceHttpRequest> ctxQeueue;
177 // If there are events, that thread will be placed in the "ready-to-serve" queue, m_requests. 146 lock (m_bycontext)
178 // If there are no events, that thread will be back to its "waiting" queue, m_longPollRequests.
179 // All other types of tasks (Inventory handlers, http-in, etc) don't have the long-poll nature,
180 // so if they aren't ready to be served by a worker thread (no events), they are placed
181 // directly back in the "ready-to-serve" queue by the worker thread.
182 while (IsRunning)
183 { 147 {
184 Thread.Sleep(500); 148 if (m_bycontext.TryGetValue(req, out ctxQeueue))
185 Watchdog.UpdateThread();
186
187// List<PollServiceHttpRequest> not_ready = new List<PollServiceHttpRequest>();
188 lock (m_longPollRequests)
189 { 149 {
190 if (m_longPollRequests.Count > 0 && IsRunning) 150 if (ctxQeueue.Count > 0)
191 { 151 {
192 List<PollServiceHttpRequest> ready = m_longPollRequests.FindAll(req => 152 PollServiceHttpRequest newreq = ctxQeueue.Dequeue();
193 (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id) || // there are events in this EQ 153 EnqueueInt(newreq);
194 (Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) // no events, but timeout 154 }
195 ); 155 else
156 {
157 m_bycontext.Remove(req);
158 }
159 }
160 }
161 }
196 162
197 ready.ForEach(req =>
198 {
199 m_requests.Enqueue(req);
200 m_longPollRequests.Remove(req);
201 });
202 163
203 } 164 public void EnqueueInt(PollServiceHttpRequest req)
165 {
166 if (m_running)
167 {
168 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll)
169 {
170 m_requests.Enqueue(req);
171 }
172 else
173 {
174 lock (m_slowRequests)
175 m_slowRequests.Enqueue(req);
176 }
177 }
178 }
179
180 private void CheckRetries()
181 {
182 while (m_running)
183
184 {
185 Thread.Sleep(100); // let the world move .. back to faster rate
186 Watchdog.UpdateThread();
187 lock (m_retryRequests)
188 {
189 while (m_retryRequests.Count > 0 && m_running)
190 m_requests.Enqueue(m_retryRequests.Dequeue());
191 }
192 slowCount++;
193 if (slowCount >= 10)
194 {
195 slowCount = 0;
204 196
197 lock (m_slowRequests)
198 {
199 while (m_slowRequests.Count > 0 && m_running)
200 m_requests.Enqueue(m_slowRequests.Dequeue());
201 }
205 } 202 }
206 } 203 }
207 } 204 }
208 205
209 public void Stop() 206 public void Stop()
210 { 207 {
211 IsRunning = false; 208 m_running = false;
212// m_timeout = -10000; // cause all to expire 209
213 Thread.Sleep(1000); // let the world move 210 Thread.Sleep(1000); // let the world move
214 211
215 foreach (Thread t in m_workerThreads) 212 foreach (Thread t in m_workerThreads)
216 Watchdog.AbortThread(t.ManagedThreadId); 213 Watchdog.AbortThread(t.ManagedThreadId);
217 214
215 // any entry in m_bycontext should have a active request on the other queues
216 // so just delete contents to easy GC
217 foreach (Queue<PollServiceHttpRequest> qu in m_bycontext.Values)
218 qu.Clear();
219 m_bycontext.Clear();
220
221 try
222 {
223 foreach (PollServiceHttpRequest req in m_retryRequests)
224 {
225 req.DoHTTPstop(m_server);
226 }
227 }
228 catch
229 {
230 }
231
218 PollServiceHttpRequest wreq; 232 PollServiceHttpRequest wreq;
233 m_retryRequests.Clear();
219 234
220 lock (m_longPollRequests) 235 lock (m_slowRequests)
221 { 236 {
222 if (m_longPollRequests.Count > 0 && IsRunning) 237 while (m_slowRequests.Count > 0)
223 m_longPollRequests.ForEach(req => m_requests.Enqueue(req)); 238 m_requests.Enqueue(m_slowRequests.Dequeue());
239
224 } 240 }
225 241
226 while (m_requests.Count() > 0) 242 while (m_requests.Count() > 0)
@@ -228,16 +244,14 @@ namespace OpenSim.Framework.Servers.HttpServer
228 try 244 try
229 { 245 {
230 wreq = m_requests.Dequeue(0); 246 wreq = m_requests.Dequeue(0);
231 ResponsesProcessed++; 247 wreq.DoHTTPstop(m_server);
232 wreq.DoHTTPGruntWork( 248
233 m_server, wreq.PollServiceArgs.NoEvents(wreq.RequestID, wreq.PollServiceArgs.Id));
234 } 249 }
235 catch 250 catch
236 { 251 {
237 } 252 }
238 } 253 }
239 254
240 m_longPollRequests.Clear();
241 m_requests.Clear(); 255 m_requests.Clear();
242 } 256 }
243 257
@@ -245,87 +259,70 @@ namespace OpenSim.Framework.Servers.HttpServer
245 259
246 private void PoolWorkerJob() 260 private void PoolWorkerJob()
247 { 261 {
248 while (IsRunning) 262 while (m_running)
249 { 263 {
250 Watchdog.UpdateThread(); 264 PollServiceHttpRequest req = m_requests.Dequeue(5000);
251 WaitPerformResponse();
252 }
253 }
254
255 public void WaitPerformResponse()
256 {
257 PollServiceHttpRequest req = m_requests.Dequeue(5000);
258// m_log.DebugFormat("[YYY]: Dequeued {0}", (req == null ? "null" : req.PollServiceArgs.Type.ToString()));
259 265
260 if (req != null) 266 Watchdog.UpdateThread();
261 { 267 if (req != null)
262 try
263 { 268 {
264 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) 269 try
265 { 270 {
266 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id); 271 if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id))
267
268 if (responsedata == null)
269 return;
270
271 // This is the event queue.
272 // Even if we're not running we can still perform responses by explicit request.
273 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll
274 || !PerformResponsesAsync)
275 { 272 {
276 try 273 Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id);
277 { 274
278 ResponsesProcessed++; 275 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue
279 req.DoHTTPGruntWork(m_server, responsedata);
280 }
281 catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream
282 {
283 // Ignore it, no need to reply
284 m_log.Error(e);
285 }
286 }
287 else
288 {
289 m_threadPool.QueueWorkItem(x =>
290 { 276 {
291 try 277 try
292 { 278 {
293 ResponsesProcessed++;
294 req.DoHTTPGruntWork(m_server, responsedata); 279 req.DoHTTPGruntWork(m_server, responsedata);
280 byContextDequeue(req);
295 } 281 }
296 catch (ObjectDisposedException e) // Browser aborted before we could read body, server closed the stream 282 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
297 { 283 {
298 // Ignore it, no need to reply 284 // Ignore it, no need to reply
299 m_log.Error(e);
300 } 285 }
301 catch (Exception e) 286 }
287 else
288 {
289 m_threadPool.QueueWorkItem(x =>
302 { 290 {
303 m_log.Error(e); 291 try
304 } 292 {
305 293 req.DoHTTPGruntWork(m_server, responsedata);
306 return null; 294 byContextDequeue(req);
307 }, null); 295 }
308 } 296 catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream
309 } 297 {
310 else 298 // Ignore it, no need to reply
311 { 299 }
312 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms) 300
313 { 301 return null;
314 ResponsesProcessed++; 302 }, null);
315 req.DoHTTPGruntWork( 303 }
316 m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
317 } 304 }
318 else 305 else
319 { 306 {
320 ReQueueEvent(req); 307 if ((Environment.TickCount - req.RequestTime) > req.PollServiceArgs.TimeOutms)
308 {
309 req.DoHTTPGruntWork(m_server,
310 req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id));
311 byContextDequeue(req);
312 }
313 else
314 {
315 ReQueueEvent(req);
316 }
321 } 317 }
322 } 318 }
323 } 319 catch (Exception e)
324 catch (Exception e) 320 {
325 { 321 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString());
326 m_log.ErrorFormat("Exception in poll service thread: " + e.ToString()); 322 }
327 } 323 }
328 } 324 }
329 } 325 }
326
330 } 327 }
331} \ No newline at end of file 328}
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 07a09e6..b330384 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -871,7 +871,7 @@ namespace OpenSim.Framework.Servers
871 } 871 }
872 } 872 }
873 873
874 protected string GetVersionText() 874 public string GetVersionText()
875 { 875 {
876 return String.Format("Version: {0} (SIMULATION/{1} - SIMULATION/{2})", 876 return String.Format("Version: {0} (SIMULATION/{1} - SIMULATION/{2})",
877 m_version, VersionInfo.SimulationServiceVersionSupportedMin, VersionInfo.SimulationServiceVersionSupportedMax); 877 m_version, VersionInfo.SimulationServiceVersionSupportedMin, VersionInfo.SimulationServiceVersionSupportedMax);
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
index 5c0e0df..1b47cc6 100644
--- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -41,7 +41,327 @@ namespace OpenSim.Framework.Servers.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class OSHttpTests : OpenSimTestCase 43 public class OSHttpTests : OpenSimTestCase
44 { 44 {
45 // we need an IHttpClientContext for our tests
46 public class TestHttpClientContext: IHttpClientContext
47 {
48 private bool _secured;
49 public bool IsSecured
50 {
51 get { return _secured; }
52 }
53 public bool Secured
54 {
55 get { return _secured; }
56 }
57
58 public TestHttpClientContext(bool secured)
59 {
60 _secured = secured;
61 }
62
63 public void Disconnect(SocketError error) {}
64 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body) {}
65 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason) {}
66 public void Respond(string body) {}
67 public void Send(byte[] buffer) {}
68 public void Send(byte[] buffer, int offset, int size) {}
69 public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body, string contentType) {}
70 public void Close() { }
71 public bool EndWhenDone { get { return false;} set { return;}}
72
73 public HTTPNetworkContext GiveMeTheNetworkStreamIKnowWhatImDoing()
74 {
75 return new HTTPNetworkContext();
76 }
77
78 public event EventHandler<DisconnectedEventArgs> Disconnected = delegate { };
79 /// <summary>
80 /// A request have been received in the context.
81 /// </summary>
82 public event EventHandler<RequestEventArgs> RequestReceived = delegate { };
83
84 public bool CanSend { get { return true; } }
85 public string RemoteEndPoint { get { return ""; } }
86 public string RemoteEndPointAddress { get { return ""; } }
87 public string RemoteEndPointPort { get { return ""; } }
88 }
89
90 public class TestHttpRequest: IHttpRequest
91 {
92 private string _uriPath;
93 public bool BodyIsComplete
94 {
95 get { return true; }
96 }
97 public string[] AcceptTypes
98 {
99 get {return _acceptTypes; }
100 }
101 private string[] _acceptTypes;
102 public Stream Body
103 {
104 get { return _body; }
105 set { _body = value;}
106 }
107 private Stream _body;
108 public ConnectionType Connection
109 {
110 get { return _connection; }
111 set { _connection = value; }
112 }
113 private ConnectionType _connection;
114 public int ContentLength
115 {
116 get { return _contentLength; }
117 set { _contentLength = value; }
118 }
119 private int _contentLength;
120 public NameValueCollection Headers
121 {
122 get { return _headers; }
123 }
124 private NameValueCollection _headers = new NameValueCollection();
125 public string HttpVersion
126 {
127 get { return _httpVersion; }
128 set { _httpVersion = value; }
129 }
130 private string _httpVersion = null;
131 public string Method
132 {
133 get { return _method; }
134 set { _method = value; }
135 }
136 private string _method = null;
137 public HttpInput QueryString
138 {
139 get { return _queryString; }
140 }
141 private HttpInput _queryString = null;
142 public Uri Uri
143 {
144 get { return _uri; }
145 set { _uri = value; }
146 }
147 private Uri _uri = null;
148 public string[] UriParts
149 {
150 get { return _uri.Segments; }
151 }
152 public HttpParam Param
153 {
154 get { return null; }
155 }
156 public HttpForm Form
157 {
158 get { return null; }
159 }
160 public bool IsAjax
161 {
162 get { return false; }
163 }
164 public RequestCookies Cookies
165 {
166 get { return null; }
167 }
168
169 public TestHttpRequest() {}
170
171 public TestHttpRequest(string contentEncoding, string contentType, string userAgent,
172 string remoteAddr, string remotePort, string[] acceptTypes,
173 ConnectionType connectionType, int contentLength, Uri uri)
174 {
175 _headers["content-encoding"] = contentEncoding;
176 _headers["content-type"] = contentType;
177 _headers["user-agent"] = userAgent;
178 _headers["remote_addr"] = remoteAddr;
179 _headers["remote_port"] = remotePort;
180
181 _acceptTypes = acceptTypes;
182 _connection = connectionType;
183 _contentLength = contentLength;
184 _uri = uri;
185 }
186
187 public void DecodeBody(FormDecoderProvider providers) {}
188 public void SetCookies(RequestCookies cookies) {}
189 public void AddHeader(string name, string value)
190 {
191 _headers.Add(name, value);
192 }
193 public int AddToBody(byte[] bytes, int offset, int length)
194 {
195 return 0;
196 }
197 public void Clear() {}
198
199 public object Clone()
200 {
201 TestHttpRequest clone = new TestHttpRequest();
202 clone._acceptTypes = _acceptTypes;
203 clone._connection = _connection;
204 clone._contentLength = _contentLength;
205 clone._uri = _uri;
206 clone._headers = new NameValueCollection(_headers);
207
208 return clone;
209 }
210 public IHttpResponse CreateResponse(IHttpClientContext context)
211 {
212 return new HttpResponse(context, this);
213 }
214 /// <summary>
215 /// Path and query (will be merged with the host header) and put in Uri
216 /// </summary>
217 /// <see cref="Uri"/>
218 public string UriPath
219 {
220 get { return _uriPath; }
221 set
222 {
223 _uriPath = value;
224
225 }
226 }
227
228 }
229
230 public class TestHttpResponse: IHttpResponse
231 {
232 public Stream Body
233 {
234 get { return _body; }
235
236 set { _body = value; }
237 }
238 private Stream _body;
239
240 public string ProtocolVersion
241 {
242 get { return _protocolVersion; }
243 set { _protocolVersion = value; }
244 }
245 private string _protocolVersion;
246
247 public bool Chunked
248 {
249 get { return _chunked; }
250
251 set { _chunked = value; }
252 }
253 private bool _chunked;
254
255 public ConnectionType Connection
256 {
257 get { return _connection; }
258
259 set { _connection = value; }
260 }
261 private ConnectionType _connection;
262
263 public Encoding Encoding
264 {
265 get { return _encoding; }
266
267 set { _encoding = value; }
268 }
269 private Encoding _encoding;
270
271 public int KeepAlive
272 {
273 get { return _keepAlive; }
274
275 set { _keepAlive = value; }
276 }
277 private int _keepAlive;
278
279 public HttpStatusCode Status
280 {
281 get { return _status; }
282
283 set { _status = value; }
284 }
285 private HttpStatusCode _status;
286
287 public string Reason
288 {
289 get { return _reason; }
290
291 set { _reason = value; }
292 }
293 private string _reason;
294
295 public long ContentLength
296 {
297 get { return _contentLength; }
298
299 set { _contentLength = value; }
300 }
301 private long _contentLength;
302
303 public string ContentType
304 {
305 get { return _contentType; }
306
307 set { _contentType = value; }
308 }
309 private string _contentType;
310
311 public bool HeadersSent
312 {
313 get { return _headersSent; }
314 }
315 private bool _headersSent;
316
317 public bool Sent
318 {
319 get { return _sent; }
320 }
321 private bool _sent;
322
323 public ResponseCookies Cookies
324 {
325 get { return _cookies; }
326 }
327 private ResponseCookies _cookies = null;
328
329 public TestHttpResponse()
330 {
331 _headersSent = false;
332 _sent = false;
333 }
334
335 public void AddHeader(string name, string value) {}
336 public void Send()
337 {
338 if (!_headersSent) SendHeaders();
339 if (_sent) throw new InvalidOperationException("stuff already sent");
340 _sent = true;
341 }
342
343 public void SendBody(byte[] buffer, int offset, int count)
344 {
345 if (!_headersSent) SendHeaders();
346 _sent = true;
347 }
348 public void SendBody(byte[] buffer)
349 {
350 if (!_headersSent) SendHeaders();
351 _sent = true;
352 }
353
354 public void SendHeaders()
355 {
356 if (_headersSent) throw new InvalidOperationException("headers already sent");
357 _headersSent = true;
358 }
359
360 public void Redirect(Uri uri) {}
361 public void Redirect(string url) {}
362 }
363
364
45 public OSHttpRequest req0; 365 public OSHttpRequest req0;
46 public OSHttpRequest req1; 366 public OSHttpRequest req1;
47 367
@@ -113,4 +433,4 @@ namespace OpenSim.Framework.Servers.Tests
113 Assert.That(rsp0.ContentType, Is.EqualTo("text/xml")); 433 Assert.That(rsp0.ContentType, Is.EqualTo("text/xml"));
114 } 434 }
115 } 435 }
116} \ No newline at end of file 436}
diff --git a/OpenSim/Framework/SimStats.cs b/OpenSim/Framework/SimStats.cs
index 3d8f32f..a811187 100644
--- a/OpenSim/Framework/SimStats.cs
+++ b/OpenSim/Framework/SimStats.cs
@@ -55,13 +55,19 @@ namespace OpenSim.Framework
55 get { return m_regionBlock; } 55 get { return m_regionBlock; }
56 } 56 }
57 private SimStatsPacket.RegionBlock m_regionBlock; 57 private SimStatsPacket.RegionBlock m_regionBlock;
58 58
59 public SimStatsPacket.StatBlock[] StatsBlock 59 public SimStatsPacket.StatBlock[] StatsBlock
60 { 60 {
61 get { return m_statsBlock; } 61 get { return m_statsBlock; }
62 } 62 }
63 private SimStatsPacket.StatBlock[] m_statsBlock; 63 private SimStatsPacket.StatBlock[] m_statsBlock;
64 64
65 public SimStatsPacket.StatBlock[] ExtraStatsBlock
66 {
67 get { return m_extraStatsBlock; }
68 }
69 private SimStatsPacket.StatBlock[] m_extraStatsBlock;
70
65 public uint RegionFlags 71 public uint RegionFlags
66 { 72 {
67 get { return m_regionFlags; } 73 get { return m_regionFlags; }
@@ -82,7 +88,8 @@ namespace OpenSim.Framework
82 88
83 public SimStats( 89 public SimStats(
84 uint regionX, uint regionY, uint regionFlags, uint objectCapacity, 90 uint regionX, uint regionY, uint regionFlags, uint objectCapacity,
85 SimStatsPacket.RegionBlock regionBlock, SimStatsPacket.StatBlock[] statsBlock, UUID pRUUID) 91 SimStatsPacket.RegionBlock regionBlock, SimStatsPacket.StatBlock[] statsBlock,
92 SimStatsPacket.StatBlock[] ExtraStatsBlock, UUID pRUUID)
86 { 93 {
87 regionUUID = pRUUID; 94 regionUUID = pRUUID;
88 m_regionX = regionX; 95 m_regionX = regionX;
@@ -91,6 +98,7 @@ namespace OpenSim.Framework
91 m_objectCapacity = objectCapacity; 98 m_objectCapacity = objectCapacity;
92 m_regionBlock = regionBlock; 99 m_regionBlock = regionBlock;
93 m_statsBlock = statsBlock; 100 m_statsBlock = statsBlock;
101 m_extraStatsBlock = ExtraStatsBlock;
94 } 102 }
95 } 103 }
96} 104}
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs
index 8af2c41..2c20ef7 100644
--- a/OpenSim/Framework/TaskInventoryDictionary.cs
+++ b/OpenSim/Framework/TaskInventoryDictionary.cs
@@ -27,9 +27,13 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Threading;
31using System.Reflection;
30using System.Xml; 32using System.Xml;
33using System.Diagnostics;
31using System.Xml.Schema; 34using System.Xml.Schema;
32using System.Xml.Serialization; 35using System.Xml.Serialization;
36using log4net;
33using OpenMetaverse; 37using OpenMetaverse;
34 38
35namespace OpenSim.Framework 39namespace OpenSim.Framework
@@ -47,6 +51,180 @@ namespace OpenSim.Framework
47 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 52
49 private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); 53 private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem));
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Thread LockedByThread;
57// private string WriterStack;
58
59// private Dictionary<Thread, string> ReadLockers =
60// new Dictionary<Thread, string>();
61
62 /// <value>
63 /// An advanced lock for inventory data
64 /// </value>
65 private volatile System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim();
66
67 /// <summary>
68 /// Are we readlocked by the calling thread?
69 /// </summary>
70 public bool IsReadLockedByMe()
71 {
72 if (m_itemLock.RecursiveReadCount > 0)
73 {
74 return true;
75 }
76 else
77 {
78 return false;
79 }
80 }
81
82 /// <summary>
83 /// Lock our inventory list for reading (many can read, one can write)
84 /// </summary>
85 public void LockItemsForRead(bool locked)
86 {
87 if (locked)
88 {
89 if (m_itemLock.IsWriteLockHeld && LockedByThread != null)
90 {
91 if (!LockedByThread.IsAlive)
92 {
93 //Locked by dead thread, reset.
94 m_itemLock = new System.Threading.ReaderWriterLockSlim();
95 }
96 }
97
98 if (m_itemLock.RecursiveReadCount > 0)
99 {
100 m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
101 try
102 {
103 // That call stack is useful for end users only. RealProgrammers need a full dump. Commented.
104 // StackTrace stackTrace = new StackTrace(); // get call stack
105 // StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
106 //
107 // // write call stack method names
108 // foreach (StackFrame stackFrame in stackFrames)
109 // {
110 // m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name
111 // }
112
113 // The below is far more useful
114// System.Console.WriteLine("------------------------------------------");
115// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
116// System.Console.WriteLine("------------------------------------------");
117// foreach (KeyValuePair<Thread, string> kvp in ReadLockers)
118// {
119// System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name);
120// System.Console.WriteLine("------------------------------------------");
121// }
122 }
123 catch
124 {}
125 m_itemLock.ExitReadLock();
126 }
127 if (m_itemLock.RecursiveWriteCount > 0)
128 {
129 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
130// try
131// {
132// System.Console.WriteLine("------------------------------------------");
133// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
134// System.Console.WriteLine("------------------------------------------");
135// System.Console.WriteLine("Locker's call stack:\n" + WriterStack);
136// System.Console.WriteLine("------------------------------------------");
137// }
138// catch
139// {}
140 m_itemLock.ExitWriteLock();
141 }
142
143 while (!m_itemLock.TryEnterReadLock(60000))
144 {
145 m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
146 //if (m_itemLock.IsWriteLockHeld)
147 //{
148 m_itemLock = new System.Threading.ReaderWriterLockSlim();
149// System.Console.WriteLine("------------------------------------------");
150// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
151// System.Console.WriteLine("------------------------------------------");
152// System.Console.WriteLine("Locker's call stack:\n" + WriterStack);
153// System.Console.WriteLine("------------------------------------------");
154// LockedByThread = null;
155// ReadLockers.Clear();
156 //}
157 }
158// ReadLockers[Thread.CurrentThread] = Environment.StackTrace;
159 }
160 else
161 {
162 if (m_itemLock.RecursiveReadCount>0)
163 {
164 m_itemLock.ExitReadLock();
165 }
166// if (m_itemLock.RecursiveReadCount == 0)
167// ReadLockers.Remove(Thread.CurrentThread);
168 }
169 }
170
171 /// <summary>
172 /// Lock our inventory list for writing (many can read, one can write)
173 /// </summary>
174 public void LockItemsForWrite(bool locked)
175 {
176 if (locked)
177 {
178 //Enter a write lock, wait indefinately for one to open.
179 if (m_itemLock.RecursiveReadCount > 0)
180 {
181 m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
182 m_itemLock.ExitReadLock();
183 }
184 if (m_itemLock.RecursiveWriteCount > 0)
185 {
186 m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed.");
187
188 m_itemLock.ExitWriteLock();
189 }
190 while (!m_itemLock.TryEnterWriteLock(60000))
191 {
192 if (m_itemLock.IsWriteLockHeld)
193 {
194 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
195// System.Console.WriteLine("------------------------------------------");
196// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
197// System.Console.WriteLine("------------------------------------------");
198// System.Console.WriteLine("Locker's call stack:\n" + WriterStack);
199// System.Console.WriteLine("------------------------------------------");
200 }
201 else
202 {
203 m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by a reader. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
204// System.Console.WriteLine("------------------------------------------");
205// System.Console.WriteLine("My call stack:\n" + Environment.StackTrace);
206// System.Console.WriteLine("------------------------------------------");
207// foreach (KeyValuePair<Thread, string> kvp in ReadLockers)
208// {
209// System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name);
210// System.Console.WriteLine("------------------------------------------");
211// }
212 }
213 m_itemLock = new System.Threading.ReaderWriterLockSlim();
214// ReadLockers.Clear();
215 }
216
217 LockedByThread = Thread.CurrentThread;
218// WriterStack = Environment.StackTrace;
219 }
220 else
221 {
222 if (m_itemLock.RecursiveWriteCount > 0)
223 {
224 m_itemLock.ExitWriteLock();
225 }
226 }
227 }
50 228
51 #region ICloneable Members 229 #region ICloneable Members
52 230
@@ -54,14 +232,13 @@ namespace OpenSim.Framework
54 { 232 {
55 TaskInventoryDictionary clone = new TaskInventoryDictionary(); 233 TaskInventoryDictionary clone = new TaskInventoryDictionary();
56 234
57 lock (this) 235 m_itemLock.EnterReadLock();
236 foreach (UUID uuid in Keys)
58 { 237 {
59 foreach (UUID uuid in Keys) 238 clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone());
60 {
61 clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone());
62 }
63 } 239 }
64 240 m_itemLock.ExitReadLock();
241
65 return clone; 242 return clone;
66 } 243 }
67 244
diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index 307cb75..2ec4bd1 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -72,7 +72,7 @@ namespace OpenSim.Framework
72 private UUID _loadedID = UUID.Zero; 72 private UUID _loadedID = UUID.Zero;
73 73
74 private bool _ownerChanged = false; 74 private bool _ownerChanged = false;
75 75
76 public UUID AssetID { 76 public UUID AssetID {
77 get { 77 get {
78 return _assetID; 78 return _assetID;
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
index 6b1be4e..d2e1c6a 100644
--- a/OpenSim/Framework/TerrainData.cs
+++ b/OpenSim/Framework/TerrainData.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.IO.Compression;
31using System.Reflection; 32using System.Reflection;
32 33
33using OpenMetaverse; 34using OpenMetaverse;
@@ -48,6 +49,7 @@ namespace OpenSim.Framework
48 49
49 public abstract float this[int x, int y] { get; set; } 50 public abstract float this[int x, int y] { get; set; }
50 // Someday terrain will have caves 51 // Someday terrain will have caves
52 // at most holes :p
51 public abstract float this[int x, int y, int z] { get; set; } 53 public abstract float this[int x, int y, int z] { get; set; }
52 54
53 public abstract bool IsTaintedAt(int xx, int yy); 55 public abstract bool IsTaintedAt(int xx, int yy);
@@ -72,8 +74,8 @@ namespace OpenSim.Framework
72 return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob); 74 return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob);
73 } 75 }
74 76
75 // return a special compressed representation of the heightmap in ints 77 // return a special compressed representation of the heightmap in ushort
76 public abstract int[] GetCompressedMap(); 78 public abstract float[] GetCompressedMap();
77 public abstract float CompressionFactor { get; } 79 public abstract float CompressionFactor { get; }
78 80
79 public abstract float[] GetFloatsSerialized(); 81 public abstract float[] GetFloatsSerialized();
@@ -94,14 +96,18 @@ namespace OpenSim.Framework
94 { 96 {
95 // Terrain is 'double[256,256]' 97 // Terrain is 'double[256,256]'
96 Legacy256 = 11, 98 Legacy256 = 11,
99
97 // Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions 100 // Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions
98 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. 101 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
99 Variable2D = 22, 102 Variable2D = 22,
103 Variable2DGzip = 23,
104
100 // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions 105 // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions
101 // and third int is the 'compression factor'. The heights are compressed as 106 // and third int is the 'compression factor'. The heights are compressed as
102 // "int compressedHeight = (int)(height * compressionFactor);" 107 // "ushort compressedHeight = (ushort)(height * compressionFactor);"
103 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. 108 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
104 Compressed2D = 27, 109 Compressed2D = 27,
110
105 // A revision that is not listed above or any revision greater than this value is 'Legacy256'. 111 // A revision that is not listed above or any revision greater than this value is 'Legacy256'.
106 RevisionHigh = 1234 112 RevisionHigh = 1234
107 } 113 }
@@ -109,7 +115,7 @@ namespace OpenSim.Framework
109 // Version of terrain that is a heightmap. 115 // Version of terrain that is a heightmap.
110 // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge 116 // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge
111 // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer. 117 // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer.
112 // The heighmap is kept as an array of integers. The integer values are converted to 118 // The heighmap is kept as an array of ushorts. The ushort values are converted to
113 // and from floats by TerrainCompressionFactor. 119 // and from floats by TerrainCompressionFactor.
114 public class HeightmapTerrainData : TerrainData 120 public class HeightmapTerrainData : TerrainData
115 { 121 {
@@ -119,12 +125,12 @@ namespace OpenSim.Framework
119 // TerrainData.this[x, y] 125 // TerrainData.this[x, y]
120 public override float this[int x, int y] 126 public override float this[int x, int y]
121 { 127 {
122 get { return FromCompressedHeight(m_heightmap[x, y]); } 128 get { return m_heightmap[x, y]; }
123 set { 129 set
124 int newVal = ToCompressedHeight(value); 130 {
125 if (m_heightmap[x, y] != newVal) 131 if (m_heightmap[x, y] != value)
126 { 132 {
127 m_heightmap[x, y] = newVal; 133 m_heightmap[x, y] = value;
128 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true; 134 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
129 } 135 }
130 } 136 }
@@ -164,10 +170,9 @@ namespace OpenSim.Framework
164 // TerrainData.ClearLand(float) 170 // TerrainData.ClearLand(float)
165 public override void ClearLand(float pHeight) 171 public override void ClearLand(float pHeight)
166 { 172 {
167 int flatHeight = ToCompressedHeight(pHeight);
168 for (int xx = 0; xx < SizeX; xx++) 173 for (int xx = 0; xx < SizeX; xx++)
169 for (int yy = 0; yy < SizeY; yy++) 174 for (int yy = 0; yy < SizeY; yy++)
170 m_heightmap[xx, yy] = flatHeight; 175 m_heightmap[xx, yy] = pHeight;
171 } 176 }
172 177
173 // Return 'true' of the patch that contains these region coordinates has been modified. 178 // Return 'true' of the patch that contains these region coordinates has been modified.
@@ -177,13 +182,15 @@ namespace OpenSim.Framework
177 { 182 {
178 int tx = xx / Constants.TerrainPatchSize; 183 int tx = xx / Constants.TerrainPatchSize;
179 int ty = yy / Constants.TerrainPatchSize; 184 int ty = yy / Constants.TerrainPatchSize;
180 bool ret = m_taint[tx, ty]; 185 bool ret = m_taint[tx, ty];
181 if (ret && clearOnTest) 186 if (ret && clearOnTest)
182 m_taint[tx, ty] = false; 187 m_taint[tx, ty] = false;
183 return ret; 188 return ret;
184 } 189 }
185 190
186 // Old form that clears the taint flag when we check it. 191 // Old form that clears the taint flag when we check it.
192 // ubit: this dangerus naming should be only check without clear
193 // keeping for old modules outthere
187 public override bool IsTaintedAt(int xx, int yy) 194 public override bool IsTaintedAt(int xx, int yy)
188 { 195 {
189 return IsTaintedAt(xx, yy, true /* clearOnTest */); 196 return IsTaintedAt(xx, yy, true /* clearOnTest */);
@@ -202,8 +209,10 @@ namespace OpenSim.Framework
202 } 209 }
203 else 210 else
204 { 211 {
205 DBRevisionCode = (int)DBTerrainRevision.Compressed2D; 212 DBRevisionCode = (int)DBTerrainRevision.Variable2DGzip;
206 blob = ToCompressedTerrainSerialization(); 213// DBRevisionCode = (int)DBTerrainRevision.Variable2D;
214 blob = ToCompressedTerrainSerializationV2DGzip();
215// blob = ToCompressedTerrainSerializationV2D();
207 ret = true; 216 ret = true;
208 } 217 }
209 return ret; 218 return ret;
@@ -214,9 +223,9 @@ namespace OpenSim.Framework
214 public override float CompressionFactor { get { return m_compressionFactor; } } 223 public override float CompressionFactor { get { return m_compressionFactor; } }
215 224
216 // TerrainData.GetCompressedMap 225 // TerrainData.GetCompressedMap
217 public override int[] GetCompressedMap() 226 public override float[] GetCompressedMap()
218 { 227 {
219 int[] newMap = new int[SizeX * SizeY]; 228 float[] newMap = new float[SizeX * SizeY];
220 229
221 int ind = 0; 230 int ind = 0;
222 for (int xx = 0; xx < SizeX; xx++) 231 for (int xx = 0; xx < SizeX; xx++)
@@ -230,7 +239,7 @@ namespace OpenSim.Framework
230 public override TerrainData Clone() 239 public override TerrainData Clone()
231 { 240 {
232 HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); 241 HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
233 ret.m_heightmap = (int[,])this.m_heightmap.Clone(); 242 ret.m_heightmap = (float[,])this.m_heightmap.Clone();
234 return ret; 243 return ret;
235 } 244 }
236 245
@@ -247,7 +256,7 @@ namespace OpenSim.Framework
247 for (int jj = 0; jj < SizeY; jj++) 256 for (int jj = 0; jj < SizeY; jj++)
248 for (int ii = 0; ii < SizeX; ii++) 257 for (int ii = 0; ii < SizeX; ii++)
249 { 258 {
250 heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]); 259 heights[idx++] = m_heightmap[ii, jj];
251 } 260 }
252 261
253 return heights; 262 return heights;
@@ -259,7 +268,7 @@ namespace OpenSim.Framework
259 double[,] ret = new double[SizeX, SizeY]; 268 double[,] ret = new double[SizeX, SizeY];
260 for (int xx = 0; xx < SizeX; xx++) 269 for (int xx = 0; xx < SizeX; xx++)
261 for (int yy = 0; yy < SizeY; yy++) 270 for (int yy = 0; yy < SizeY; yy++)
262 ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]); 271 ret[xx, yy] = (double)m_heightmap[xx, yy];
263 272
264 return ret; 273 return ret;
265 } 274 }
@@ -267,19 +276,40 @@ namespace OpenSim.Framework
267 276
268 // ============================================================= 277 // =============================================================
269 278
270 private int[,] m_heightmap; 279 private float[,] m_heightmap;
271 // Remember subregions of the heightmap that has changed. 280 // Remember subregions of the heightmap that has changed.
272 private bool[,] m_taint; 281 private bool[,] m_taint;
273 282
274 // To save space (especially for large regions), keep the height as a short integer
275 // that is coded as the float height times the compression factor (usually '100' 283 // that is coded as the float height times the compression factor (usually '100'
276 // to make for two decimal points). 284 // to make for two decimal points).
277 public int ToCompressedHeight(double pHeight) 285 public short ToCompressedHeightshort(float pHeight)
286 {
287 // clamp into valid range
288 pHeight *= CompressionFactor;
289 if (pHeight < short.MinValue)
290 return short.MinValue;
291 else if (pHeight > short.MaxValue)
292 return short.MaxValue;
293 return (short)pHeight;
294 }
295
296 public ushort ToCompressedHeightushort(float pHeight)
278 { 297 {
279 return (int)(pHeight * CompressionFactor); 298 // clamp into valid range
299 pHeight *= CompressionFactor;
300 if (pHeight < ushort.MinValue)
301 return ushort.MinValue;
302 else if (pHeight > ushort.MaxValue)
303 return ushort.MaxValue;
304 return (ushort)pHeight;
280 } 305 }
281 306
282 public float FromCompressedHeight(int pHeight) 307 public float FromCompressedHeight(short pHeight)
308 {
309 return ((float)pHeight) / CompressionFactor;
310 }
311
312 public float FromCompressedHeight(ushort pHeight)
283 { 313 {
284 return ((float)pHeight) / CompressionFactor; 314 return ((float)pHeight) / CompressionFactor;
285 } 315 }
@@ -293,12 +323,12 @@ namespace OpenSim.Framework
293 SizeZ = (int)Constants.RegionHeight; 323 SizeZ = (int)Constants.RegionHeight;
294 m_compressionFactor = 100.0f; 324 m_compressionFactor = 100.0f;
295 325
296 m_heightmap = new int[SizeX, SizeY]; 326 m_heightmap = new float[SizeX, SizeY];
297 for (int ii = 0; ii < SizeX; ii++) 327 for (int ii = 0; ii < SizeX; ii++)
298 { 328 {
299 for (int jj = 0; jj < SizeY; jj++) 329 for (int jj = 0; jj < SizeY; jj++)
300 { 330 {
301 m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]); 331 m_heightmap[ii, jj] = (float)pTerrain[ii, jj];
302 332
303 } 333 }
304 } 334 }
@@ -315,14 +345,15 @@ namespace OpenSim.Framework
315 SizeY = pY; 345 SizeY = pY;
316 SizeZ = pZ; 346 SizeZ = pZ;
317 m_compressionFactor = 100.0f; 347 m_compressionFactor = 100.0f;
318 m_heightmap = new int[SizeX, SizeY]; 348 m_heightmap = new float[SizeX, SizeY];
319 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; 349 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
320 // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ); 350 // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
321 ClearTaint(); 351 ClearTaint();
322 ClearLand(0f); 352 ClearLand(0f);
323 } 353 }
324 354
325 public HeightmapTerrainData(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) 355 public HeightmapTerrainData(float[] cmap, float pCompressionFactor, int pX, int pY, int pZ)
356 : this(pX, pY, pZ)
326 { 357 {
327 m_compressionFactor = pCompressionFactor; 358 m_compressionFactor = pCompressionFactor;
328 int ind = 0; 359 int ind = 0;
@@ -333,12 +364,22 @@ namespace OpenSim.Framework
333 } 364 }
334 365
335 // Create a heighmap from a database blob 366 // Create a heighmap from a database blob
336 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ) 367 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob)
368 : this(pSizeX, pSizeY, pSizeZ)
337 { 369 {
338 switch ((DBTerrainRevision)pFormatCode) 370 switch ((DBTerrainRevision)pFormatCode)
339 { 371 {
372 case DBTerrainRevision.Variable2DGzip:
373 FromCompressedTerrainSerializationV2DGZip(pBlob);
374 m_log.DebugFormat("{0} HeightmapTerrainData create from Variable2DGzip serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
375 break;
376
377 case DBTerrainRevision.Variable2D:
378 FromCompressedTerrainSerializationV2D(pBlob);
379 m_log.DebugFormat("{0} HeightmapTerrainData create from Variable2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
380 break;
340 case DBTerrainRevision.Compressed2D: 381 case DBTerrainRevision.Compressed2D:
341 FromCompressedTerrainSerialization(pBlob); 382 FromCompressedTerrainSerialization2D(pBlob);
342 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); 383 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
343 break; 384 break;
344 default: 385 default:
@@ -373,50 +414,116 @@ namespace OpenSim.Framework
373 return ret; 414 return ret;
374 } 415 }
375 416
376 // Just create an array of doubles. Presumes the caller implicitly knows the size. 417 // Presumes the caller implicitly knows the size.
377 public void FromLegacyTerrainSerialization(byte[] pBlob) 418 public void FromLegacyTerrainSerialization(byte[] pBlob)
378 { 419 {
379 // In case database info doesn't match real terrain size, initialize the whole terrain. 420 // In case database info doesn't match real terrain size, initialize the whole terrain.
380 ClearLand(); 421 ClearLand();
381 422
382 using (MemoryStream mstr = new MemoryStream(pBlob)) 423 try
383 { 424 {
384 using (BinaryReader br = new BinaryReader(mstr)) 425 using (MemoryStream mstr = new MemoryStream(pBlob))
385 { 426 {
386 for (int xx = 0; xx < (int)Constants.RegionSize; xx++) 427 using (BinaryReader br = new BinaryReader(mstr))
387 { 428 {
388 for (int yy = 0; yy < (int)Constants.RegionSize; yy++) 429 for (int xx = 0; xx < (int)Constants.RegionSize; xx++)
389 { 430 {
390 float val = (float)br.ReadDouble(); 431 for (int yy = 0; yy < (int)Constants.RegionSize; yy++)
391 if (xx < SizeX && yy < SizeY) 432 {
392 m_heightmap[xx, yy] = ToCompressedHeight(val); 433 float val = (float)br.ReadDouble();
434
435 if (xx < SizeX && yy < SizeY)
436 m_heightmap[xx, yy] = val;
437 }
393 } 438 }
394 } 439 }
395 } 440 }
396 ClearTaint();
397 } 441 }
442 catch
443 {
444 ClearLand();
445 }
446 ClearTaint();
398 } 447 }
399 448
400 // See the reader below. 449
401 public Array ToCompressedTerrainSerialization() 450 // stores as variable2D
451 // int32 sizeX
452 // int32 sizeY
453 // float[,] array
454
455 public Array ToCompressedTerrainSerializationV2D()
402 { 456 {
403 Array ret = null; 457 Array ret = null;
404 using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(Int16)))) 458 try
405 { 459 {
406 using (BinaryWriter bw = new BinaryWriter(str)) 460 using (MemoryStream str = new MemoryStream((2 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float))))
461 {
462 using (BinaryWriter bw = new BinaryWriter(str))
463 {
464 bw.Write((Int32)SizeX);
465 bw.Write((Int32)SizeY);
466 for (int yy = 0; yy < SizeY; yy++)
467 for (int xx = 0; xx < SizeX; xx++)
468 {
469 // reduce to 1cm resolution
470 float val = (float)Math.Round(m_heightmap[xx, yy],2,MidpointRounding.ToEven);
471 bw.Write(val);
472 }
473 }
474 ret = str.ToArray();
475 }
476 }
477 catch
478 {
479
480 }
481
482 m_log.DebugFormat("{0} V2D {1} bytes",
483 LogHeader, ret.Length);
484
485 return ret;
486 }
487
488 // as above with Gzip compression
489 public Array ToCompressedTerrainSerializationV2DGzip()
490 {
491 Array ret = null;
492 try
493 {
494 using (MemoryStream inp = new MemoryStream((2 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float))))
407 { 495 {
408 bw.Write((Int32)DBTerrainRevision.Compressed2D); 496 using (BinaryWriter bw = new BinaryWriter(inp))
409 bw.Write((Int32)SizeX); 497 {
410 bw.Write((Int32)SizeY); 498 bw.Write((Int32)SizeX);
411 bw.Write((Int32)CompressionFactor); 499 bw.Write((Int32)SizeY);
412 for (int yy = 0; yy < SizeY; yy++) 500 for (int yy = 0; yy < SizeY; yy++)
413 for (int xx = 0; xx < SizeX; xx++) 501 for (int xx = 0; xx < SizeX; xx++)
502 {
503 bw.Write((float)m_heightmap[xx, yy]);
504 }
505
506 bw.Flush();
507 inp.Seek(0, SeekOrigin.Begin);
508
509 using (MemoryStream outputStream = new MemoryStream())
414 { 510 {
415 bw.Write((Int16)m_heightmap[xx, yy]); 511 using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress))
512 {
513 inp.CopyStream(compressionStream, int.MaxValue);
514 compressionStream.Close();
515 ret = outputStream.ToArray();
516 }
416 } 517 }
518 }
417 } 519 }
418 ret = str.ToArray();
419 } 520 }
521 catch
522 {
523
524 }
525 m_log.DebugFormat("{0} V2DGzip {1} bytes",
526 LogHeader, ret.Length);
420 return ret; 527 return ret;
421 } 528 }
422 529
@@ -426,7 +533,7 @@ namespace OpenSim.Framework
426 // the forth int is the compression factor for the following int16s 533 // the forth int is the compression factor for the following int16s
427 // This is just sets heightmap info. The actual size of the region was set on this instance's 534 // This is just sets heightmap info. The actual size of the region was set on this instance's
428 // creation and any heights not initialized by theis blob are set to the default height. 535 // creation and any heights not initialized by theis blob are set to the default height.
429 public void FromCompressedTerrainSerialization(byte[] pBlob) 536 public void FromCompressedTerrainSerialization2D(byte[] pBlob)
430 { 537 {
431 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; 538 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor;
432 539
@@ -448,7 +555,7 @@ namespace OpenSim.Framework
448 { 555 {
449 for (int xx = 0; xx < hmSizeX; xx++) 556 for (int xx = 0; xx < hmSizeX; xx++)
450 { 557 {
451 Int16 val = br.ReadInt16(); 558 float val = FromCompressedHeight(br.ReadInt16());
452 if (xx < SizeX && yy < SizeY) 559 if (xx < SizeX && yy < SizeY)
453 m_heightmap[xx, yy] = val; 560 m_heightmap[xx, yy] = val;
454 } 561 }
@@ -456,9 +563,112 @@ namespace OpenSim.Framework
456 } 563 }
457 ClearTaint(); 564 ClearTaint();
458 565
459 m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", 566 m_log.DebugFormat("{0} Read (compressed2D) heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}",
460 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); 567 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor);
461 } 568 }
462 } 569 }
570
571 // Initialize heightmap from blob consisting of:
572 // int32, int32, int32, float[]
573 // where the first int32 is format code, next two int32s are the X and y of heightmap data
574 // This is just sets heightmap info. The actual size of the region was set on this instance's
575 // creation and any heights not initialized by theis blob are set to the default height.
576 public void FromCompressedTerrainSerializationV2D(byte[] pBlob)
577 {
578 Int32 hmSizeX, hmSizeY;
579 try
580 {
581 using (MemoryStream mstr = new MemoryStream(pBlob))
582 {
583 using (BinaryReader br = new BinaryReader(mstr))
584 {
585 hmSizeX = br.ReadInt32();
586 hmSizeY = br.ReadInt32();
587
588 // In case database info doesn't match real terrain size, initialize the whole terrain.
589 ClearLand();
590
591 for (int yy = 0; yy < hmSizeY; yy++)
592 {
593 for (int xx = 0; xx < hmSizeX; xx++)
594 {
595 float val = br.ReadSingle();
596 if (xx < SizeX && yy < SizeY)
597 m_heightmap[xx, yy] = val;
598 }
599 }
600 }
601 }
602 }
603 catch (Exception e)
604 {
605 ClearTaint();
606 m_log.ErrorFormat("{0} 2D error: {1} - terrain may be damaged",
607 LogHeader, e.Message);
608 return;
609 }
610 ClearTaint();
611
612 m_log.DebugFormat("{0} V2D Heightmap size=<{1},{2}>. Region size=<{3},{4}>",
613 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY);
614
615 }
616
617 // as above but Gzip compressed
618 public void FromCompressedTerrainSerializationV2DGZip(byte[] pBlob)
619 {
620 m_log.InfoFormat("{0} VD2Gzip {1} bytes input",
621 LogHeader, pBlob.Length);
622
623 Int32 hmSizeX, hmSizeY;
624
625 try
626 {
627 using (MemoryStream outputStream = new MemoryStream())
628 {
629 using (MemoryStream inputStream = new MemoryStream(pBlob))
630 {
631 using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress))
632 {
633 decompressionStream.Flush();
634 decompressionStream.CopyTo(outputStream);
635 }
636 }
637
638 outputStream.Seek(0, SeekOrigin.Begin);
639
640 using (BinaryReader br = new BinaryReader(outputStream))
641 {
642 hmSizeX = br.ReadInt32();
643 hmSizeY = br.ReadInt32();
644
645 // In case database info doesn't match real terrain size, initialize the whole terrain.
646 ClearLand();
647
648 for (int yy = 0; yy < hmSizeY; yy++)
649 {
650 for (int xx = 0; xx < hmSizeX; xx++)
651 {
652 float val = br.ReadSingle();
653 if (xx < SizeX && yy < SizeY)
654 m_heightmap[xx, yy] = val;
655 }
656 }
657 }
658 }
659 }
660 catch( Exception e)
661 {
662 ClearTaint();
663 m_log.ErrorFormat("{0} V2DGzip error: {1} - terrain may be damaged",
664 LogHeader, e.Message);
665 return;
666 }
667
668 ClearTaint();
669 m_log.DebugFormat("{0} V2DGzip. Heightmap size=<{1},{2}>. Region size=<{3},{4}>",
670 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY);
671
672 }
463 } 673 }
464} 674}
diff --git a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
index 95e9439..e8ae728 100644
--- a/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
+++ b/OpenSim/Framework/Tests/AgentCircuitDataTest.cs
@@ -311,8 +311,9 @@ namespace OpenSim.Framework.Tests
311 Agent1Data.SessionID = SessionId; 311 Agent1Data.SessionID = SessionId;
312 Agent1Data.startpos = StartPos; 312 Agent1Data.startpos = StartPos;
313 313
314 EntityTransferContext ctx = new EntityTransferContext();
314 OSDMap map2; 315 OSDMap map2;
315 OSDMap map = Agent1Data.PackAgentCircuitData(); 316 OSDMap map = Agent1Data.PackAgentCircuitData(ctx);
316 try 317 try
317 { 318 {
318 string str = OSDParser.SerializeJsonString(map); 319 string str = OSDParser.SerializeJsonString(map);
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index 3f0a031..d8072c7 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -116,7 +116,8 @@ namespace OpenSim.Framework.Tests
116 position2 = new AgentPosition(); 116 position2 = new AgentPosition();
117 117
118 Assert.IsFalse(position2.AgentID == position1.AgentID, "Test Error, position2 should be a blank uninitialized AgentPosition"); 118 Assert.IsFalse(position2.AgentID == position1.AgentID, "Test Error, position2 should be a blank uninitialized AgentPosition");
119 position2.Unpack(position1.Pack(), null); 119 EntityTransferContext ctx = new EntityTransferContext();
120 position2.Unpack(position1.Pack(ctx), null, ctx);
120 121
121 Assert.IsTrue(position2.AgentID == position1.AgentID, "Agent ID didn't unpack the same way it packed"); 122 Assert.IsTrue(position2.AgentID == position1.AgentID, "Agent ID didn't unpack the same way it packed");
122 Assert.IsTrue(position2.Position == position1.Position, "Position didn't unpack the same way it packed"); 123 Assert.IsTrue(position2.Position == position1.Position, "Position didn't unpack the same way it packed");
@@ -218,12 +219,12 @@ namespace OpenSim.Framework.Tests
218 BannedHostNameMask = string.Empty, 219 BannedHostNameMask = string.Empty,
219 BannedUserID = bannedUserId} 220 BannedUserID = bannedUserId}
220 ); 221 );
221 Assert.IsTrue(es.IsBanned(bannedUserId), "User Should be banned but is not."); 222 Assert.IsTrue(es.IsBanned(bannedUserId, 32), "User Should be banned but is not.");
222 Assert.IsFalse(es.IsBanned(UUID.Zero), "User Should not be banned but is."); 223 Assert.IsFalse(es.IsBanned(UUID.Zero, 32), "User Should not be banned but is.");
223 224
224 es.RemoveBan(bannedUserId); 225 es.RemoveBan(bannedUserId);
225 226
226 Assert.IsFalse(es.IsBanned(bannedUserId), "User Should not be banned but is."); 227 Assert.IsFalse(es.IsBanned(bannedUserId, 32), "User Should not be banned but is.");
227 228
228 es.AddEstateManager(UUID.Zero); 229 es.AddEstateManager(UUID.Zero);
229 230
@@ -305,4 +306,4 @@ namespace OpenSim.Framework.Tests
305 306
306 } 307 }
307 } 308 }
308} \ No newline at end of file 309}
diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs
index ca4b126..87899f0 100644
--- a/OpenSim/Framework/ThrottleOutPacketType.cs
+++ b/OpenSim/Framework/ThrottleOutPacketType.cs
@@ -47,6 +47,8 @@ namespace OpenSim.Framework
47 Texture = 5, 47 Texture = 5,
48 /// <summary>Non-texture assets</summary> 48 /// <summary>Non-texture assets</summary>
49 Asset = 6, 49 Asset = 6,
50
51 HighPriority = 128,
50 } 52 }
51 53
52 [Flags] 54 [Flags]
diff --git a/OpenSim/Framework/UserProfileData.cs b/OpenSim/Framework/UserProfileData.cs
index 266ccf0..f7069a5 100644
--- a/OpenSim/Framework/UserProfileData.cs
+++ b/OpenSim/Framework/UserProfileData.cs
@@ -160,7 +160,7 @@ namespace OpenSim.Framework
160 public virtual ulong HomeRegion 160 public virtual ulong HomeRegion
161 { 161 {
162 get 162 get
163 { 163 {
164 return Util.RegionWorldLocToHandle(Util.RegionToWorldLoc(m_homeRegionX), Util.RegionToWorldLoc(m_homeRegionY)); 164 return Util.RegionWorldLocToHandle(Util.RegionToWorldLoc(m_homeRegionX), Util.RegionToWorldLoc(m_homeRegionY));
165 // return Utils.UIntsToLong( m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize); 165 // return Utils.UIntsToLong( m_homeRegionX * (uint)Constants.RegionSize, m_homeRegionY * (uint)Constants.RegionSize);
166 } 166 }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 1f74168..4dafaef 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -61,6 +61,15 @@ namespace OpenSim.Framework
61 public enum PermissionMask : uint 61 public enum PermissionMask : uint
62 { 62 {
63 None = 0, 63 None = 0,
64
65 // folded perms
66 foldedTransfer = 1,
67 foldedModify = 1 << 1,
68 foldedCopy = 1 << 2,
69
70 foldedMask = 0x07,
71
72 //
64 Transfer = 1 << 13, 73 Transfer = 1 << 13,
65 Modify = 1 << 14, 74 Modify = 1 << 14,
66 Copy = 1 << 15, 75 Copy = 1 << 15,
@@ -131,10 +140,14 @@ namespace OpenSim.Framework
131 140
132 public static readonly int MAX_THREADPOOL_LEVEL = 3; 141 public static readonly int MAX_THREADPOOL_LEVEL = 3;
133 142
143 public static double TimeStampClockPeriodMS;
144
134 static Util() 145 static Util()
135 { 146 {
136 LogThreadPool = 0; 147 LogThreadPool = 0;
137 LogOverloads = true; 148 LogOverloads = true;
149 TimeStampClockPeriodMS = 1000.0D / (double)Stopwatch.Frequency;
150 m_log.InfoFormat("[UTIL] TimeStamp clock with period of {0}ms", Math.Round(TimeStampClockPeriodMS,6,MidpointRounding.AwayFromZero));
138 } 151 }
139 152
140 private static uint nextXferID = 5000; 153 private static uint nextXferID = 5000;
@@ -267,14 +280,12 @@ namespace OpenSim.Framework
267 /// </summary> 280 /// </summary>
268 /// <param name="a">A 3d vector</param> 281 /// <param name="a">A 3d vector</param>
269 /// <returns>A new vector which is normalized form of the vector</returns> 282 /// <returns>A new vector which is normalized form of the vector</returns>
270 /// <remarks>The vector paramater cannot be <0,0,0></remarks> 283
271 public static Vector3 GetNormalizedVector(Vector3 a) 284 public static Vector3 GetNormalizedVector(Vector3 a)
272 { 285 {
273 if (IsZeroVector(a)) 286 Vector3 v = new Vector3(a.X, a.Y, a.Z);
274 throw new ArgumentException("Vector paramater cannot be a zero vector."); 287 v.Normalize();
275 288 return v;
276 float Mag = (float) GetMagnitude(a);
277 return new Vector3(a.X / Mag, a.Y / Mag, a.Z / Mag);
278 } 289 }
279 290
280 /// <summary> 291 /// <summary>
@@ -641,19 +652,25 @@ namespace OpenSim.Framework
641 /// </summary> 652 /// </summary>
642 /// <param name="data"></param> 653 /// <param name="data"></param>
643 /// <returns></returns> 654 /// <returns></returns>
655
644 public static string Md5Hash(string data) 656 public static string Md5Hash(string data)
645 { 657 {
646 byte[] dataMd5 = ComputeMD5Hash(data); 658 return Md5Hash(data, Encoding.Default);
659 }
660
661 public static string Md5Hash(string data, Encoding encoding)
662 {
663 byte[] dataMd5 = ComputeMD5Hash(data, encoding);
647 StringBuilder sb = new StringBuilder(); 664 StringBuilder sb = new StringBuilder();
648 for (int i = 0; i < dataMd5.Length; i++) 665 for (int i = 0; i < dataMd5.Length; i++)
649 sb.AppendFormat("{0:x2}", dataMd5[i]); 666 sb.AppendFormat("{0:x2}", dataMd5[i]);
650 return sb.ToString(); 667 return sb.ToString();
651 } 668 }
652 669
653 private static byte[] ComputeMD5Hash(string data) 670 private static byte[] ComputeMD5Hash(string data, Encoding encoding)
654 { 671 {
655 MD5 md5 = MD5.Create(); 672 MD5 md5 = MD5.Create();
656 return md5.ComputeHash(Encoding.Default.GetBytes(data)); 673 return md5.ComputeHash(encoding.GetBytes(data));
657 } 674 }
658 675
659 /// <summary> 676 /// <summary>
@@ -661,6 +678,12 @@ namespace OpenSim.Framework
661 /// </summary> 678 /// </summary>
662 /// <param name="data"></param> 679 /// <param name="data"></param>
663 /// <returns></returns> 680 /// <returns></returns>
681
682 public static string SHA1Hash(string data, Encoding enc)
683 {
684 return SHA1Hash(enc.GetBytes(data));
685 }
686
664 public static string SHA1Hash(string data) 687 public static string SHA1Hash(string data)
665 { 688 {
666 return SHA1Hash(Encoding.Default.GetBytes(data)); 689 return SHA1Hash(Encoding.Default.GetBytes(data));
@@ -714,17 +737,26 @@ namespace OpenSim.Framework
714 /// <param name="oldy">Old region y-coord</param> 737 /// <param name="oldy">Old region y-coord</param>
715 /// <param name="newy">New region y-coord</param> 738 /// <param name="newy">New region y-coord</param>
716 /// <returns></returns> 739 /// <returns></returns>
717 public static bool IsOutsideView(float drawdist, uint oldx, uint newx, uint oldy, uint newy) 740 public static bool IsOutsideView(float drawdist, uint oldx, uint newx, uint oldy, uint newy,
741 int oldsizex, int oldsizey, int newsizex, int newsizey)
718 { 742 {
719 int dd = (int)((drawdist + Constants.RegionSize - 1) / Constants.RegionSize); 743 // we still need to make sure we see new region 1stNeighbors
720 744
721 int startX = (int)oldx - dd; 745 oldx *= Constants.RegionSize;
722 int startY = (int)oldy - dd; 746 newx *= Constants.RegionSize;
747 if (oldx + oldsizex + drawdist < newx)
748 return true;
749 if (newx + newsizex + drawdist < oldx)
750 return true;
723 751
724 int endX = (int)oldx + dd; 752 oldy *= Constants.RegionSize;
725 int endY = (int)oldy + dd; 753 newy *= Constants.RegionSize;
754 if (oldy + oldsizey + drawdist < newy)
755 return true;
756 if (newy + newsizey + drawdist< oldy)
757 return true;
726 758
727 return (newx < startX || endX < newx || newy < startY || endY < newy); 759 return false;
728 } 760 }
729 761
730 public static string FieldToString(byte[] bytes) 762 public static string FieldToString(byte[] bytes)
@@ -805,6 +837,16 @@ namespace OpenSim.Framework
805 } 837 }
806 838
807 /// <summary> 839 /// <summary>
840 /// Converts a URL to a IPAddress
841 /// </summary>
842 /// <param name="url">URL Standard Format</param>
843 /// <returns>A resolved IP Address</returns>
844 public static IPAddress GetHostFromURL(string url)
845 {
846 return GetHostFromDNS(url.Split(new char[] {'/', ':'})[3]);
847 }
848
849 /// <summary>
808 /// Returns a IP address from a specified DNS, favouring IPv4 addresses. 850 /// Returns a IP address from a specified DNS, favouring IPv4 addresses.
809 /// </summary> 851 /// </summary>
810 /// <param name="dnsAddress">DNS Hostname</param> 852 /// <param name="dnsAddress">DNS Hostname</param>
@@ -1065,6 +1107,25 @@ namespace OpenSim.Framework
1065 } 1107 }
1066 } 1108 }
1067 1109
1110 public static string GetConfigVarWithDefaultSection(IConfigSource config, string varname, string section)
1111 {
1112 // First, check the Startup section, the default section
1113 IConfig cnf = config.Configs["Startup"];
1114 if (cnf == null)
1115 return string.Empty;
1116 string val = cnf.GetString(varname, string.Empty);
1117
1118 // Then check for an overwrite of the default in the given section
1119 if (!string.IsNullOrEmpty(section))
1120 {
1121 cnf = config.Configs[section];
1122 if (cnf != null)
1123 val = cnf.GetString(varname, val);
1124 }
1125
1126 return val;
1127 }
1128
1068 /// <summary> 1129 /// <summary>
1069 /// Gets the value of a configuration variable by looking into 1130 /// Gets the value of a configuration variable by looking into
1070 /// multiple sections in order. The latter sections overwrite 1131 /// multiple sections in order. The latter sections overwrite
@@ -1388,6 +1449,46 @@ namespace OpenSim.Framework
1388 return ret; 1449 return ret;
1389 } 1450 }
1390 1451
1452 public static string Compress(string text)
1453 {
1454 byte[] buffer = Util.UTF8.GetBytes(text);
1455 MemoryStream memory = new MemoryStream();
1456 using (GZipStream compressor = new GZipStream(memory, CompressionMode.Compress, true))
1457 {
1458 compressor.Write(buffer, 0, buffer.Length);
1459 }
1460
1461 memory.Position = 0;
1462
1463 byte[] compressed = new byte[memory.Length];
1464 memory.Read(compressed, 0, compressed.Length);
1465
1466 byte[] compressedBuffer = new byte[compressed.Length + 4];
1467 Buffer.BlockCopy(compressed, 0, compressedBuffer, 4, compressed.Length);
1468 Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, compressedBuffer, 0, 4);
1469 return Convert.ToBase64String(compressedBuffer);
1470 }
1471
1472 public static string Decompress(string compressedText)
1473 {
1474 byte[] compressedBuffer = Convert.FromBase64String(compressedText);
1475 using (MemoryStream memory = new MemoryStream())
1476 {
1477 int msgLength = BitConverter.ToInt32(compressedBuffer, 0);
1478 memory.Write(compressedBuffer, 4, compressedBuffer.Length - 4);
1479
1480 byte[] buffer = new byte[msgLength];
1481
1482 memory.Position = 0;
1483 using (GZipStream decompressor = new GZipStream(memory, CompressionMode.Decompress))
1484 {
1485 decompressor.Read(buffer, 0, buffer.Length);
1486 }
1487
1488 return Util.UTF8.GetString(buffer);
1489 }
1490 }
1491
1391 /// <summary> 1492 /// <summary>
1392 /// Copy data from one stream to another, leaving the read position of both streams at the beginning. 1493 /// Copy data from one stream to another, leaving the read position of both streams at the beginning.
1393 /// </summary> 1494 /// </summary>
@@ -1524,19 +1625,19 @@ namespace OpenSim.Framework
1524 { 1625 {
1525 string os = String.Empty; 1626 string os = String.Empty;
1526 1627
1527 if (Environment.OSVersion.Platform != PlatformID.Unix) 1628// if (Environment.OSVersion.Platform != PlatformID.Unix)
1528 { 1629// {
1529 os = Environment.OSVersion.ToString(); 1630// os = Environment.OSVersion.ToString();
1530 } 1631// }
1531 else 1632// else
1532 { 1633// {
1533 os = ReadEtcIssue(); 1634// os = ReadEtcIssue();
1534 } 1635// }
1535 1636//
1536 if (os.Length > 45) 1637// if (os.Length > 45)
1537 { 1638// {
1538 os = os.Substring(0, 45); 1639// os = os.Substring(0, 45);
1539 } 1640// }
1540 1641
1541 return os; 1642 return os;
1542 } 1643 }
@@ -1645,7 +1746,7 @@ namespace OpenSim.Framework
1645 1746
1646 public static Guid GetHashGuid(string data, string salt) 1747 public static Guid GetHashGuid(string data, string salt)
1647 { 1748 {
1648 byte[] hash = ComputeMD5Hash(data + salt); 1749 byte[] hash = ComputeMD5Hash(data + salt, Encoding.Default);
1649 1750
1650 //string s = BitConverter.ToString(hash); 1751 //string s = BitConverter.ToString(hash);
1651 1752
@@ -1792,6 +1893,32 @@ namespace OpenSim.Framework
1792 return found.ToArray(); 1893 return found.ToArray();
1793 } 1894 }
1794 1895
1896 public static string ServerURI(string uri)
1897 {
1898 if (uri == string.Empty)
1899 return string.Empty;
1900
1901 // Get rid of eventual slashes at the end
1902 uri = uri.TrimEnd('/');
1903
1904 IPAddress ipaddr1 = null;
1905 string port1 = "";
1906 try
1907 {
1908 ipaddr1 = Util.GetHostFromURL(uri);
1909 }
1910 catch { }
1911
1912 try
1913 {
1914 port1 = uri.Split(new char[] { ':' })[2];
1915 }
1916 catch { }
1917
1918 // We tried our best to convert the domain names to IP addresses
1919 return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri;
1920 }
1921
1795 /// <summary> 1922 /// <summary>
1796 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary. 1923 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary.
1797 /// </summary> 1924 /// </summary>
@@ -1895,6 +2022,56 @@ namespace OpenSim.Framework
1895 } 2022 }
1896 2023
1897 /// <summary> 2024 /// <summary>
2025 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to MaxLength bytes if necessary.
2026 /// </summary>
2027 /// <param name="str">
2028 /// If null or empty, then an bytes[0] is returned.
2029 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
2030 /// </param>
2031 /// <param name="args">
2032 /// Arguments to substitute into the string via the {} mechanism.
2033 /// </param>
2034 /// <returns></returns>
2035 public static byte[] StringToBytes(string str, int MaxLength, params object[] args)
2036 {
2037 return StringToBytes1024(string.Format(str, args), MaxLength);
2038 }
2039
2040 /// <summary>
2041 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to MaxLength bytes if necessary.
2042 /// </summary>
2043 /// <param name="str">
2044 /// If null or empty, then an bytes[0] is returned.
2045 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
2046 /// </param>
2047 /// <returns></returns>
2048 public static byte[] StringToBytes(string str, int MaxLength)
2049 {
2050 if (String.IsNullOrEmpty(str))
2051 return Utils.EmptyBytes;
2052
2053 if (!str.EndsWith("\0"))
2054 str += "\0";
2055
2056 // Because this is UTF-8 encoding and not ASCII, it's possible we
2057 // might have gotten an oversized array even after the string trim
2058 byte[] data = UTF8.GetBytes(str);
2059
2060 if (data.Length > MaxLength)
2061 {
2062 int cut = MaxLength -1 ;
2063 if((data[cut] & 0x80 ) != 0 )
2064 {
2065 while(cut > 0 && (data[cut] & 0xc0) != 0xc0)
2066 cut--;
2067 }
2068 Array.Resize<byte>(ref data, cut + 1);
2069 data[cut] = 0;
2070 }
2071
2072 return data;
2073 }
2074 /// <summary>
1898 /// Pretty format the hashtable contents to a single line. 2075 /// Pretty format the hashtable contents to a single line.
1899 /// </summary> 2076 /// </summary>
1900 /// <remarks> 2077 /// <remarks>
@@ -2004,7 +2181,7 @@ namespace OpenSim.Framework
2004 2181
2005 STPStartInfo startInfo = new STPStartInfo(); 2182 STPStartInfo startInfo = new STPStartInfo();
2006 startInfo.ThreadPoolName = "Util"; 2183 startInfo.ThreadPoolName = "Util";
2007 startInfo.IdleTimeout = 2000; 2184 startInfo.IdleTimeout = 20000;
2008 startInfo.MaxWorkerThreads = maxThreads; 2185 startInfo.MaxWorkerThreads = maxThreads;
2009 startInfo.MinWorkerThreads = minThreads; 2186 startInfo.MinWorkerThreads = minThreads;
2010 2187
@@ -2557,6 +2734,13 @@ namespace OpenSim.Framework
2557 return tcA - tcB; 2734 return tcA - tcB;
2558 } 2735 }
2559 2736
2737 // returns a timestamp in ms as double
2738 // using the time resolution avaiable to StopWatch
2739 public static double GetTimeStampMS()
2740 {
2741 return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriodMS;
2742 }
2743
2560 /// <summary> 2744 /// <summary>
2561 /// Formats a duration (given in milliseconds). 2745 /// Formats a duration (given in milliseconds).
2562 /// </summary> 2746 /// </summary>
diff --git a/OpenSim/Framework/WearableCacheItem.cs b/OpenSim/Framework/WearableCacheItem.cs
index 1aecf79..af28abc 100644
--- a/OpenSim/Framework/WearableCacheItem.cs
+++ b/OpenSim/Framework/WearableCacheItem.cs
@@ -43,12 +43,13 @@ namespace OpenSim.Framework
43 43
44 public static WearableCacheItem[] GetDefaultCacheItem() 44 public static WearableCacheItem[] GetDefaultCacheItem()
45 { 45 {
46 int itemmax = 21; 46 int itemmax = AvatarAppearance.TEXTURE_COUNT;
47 WearableCacheItem[] retitems = new WearableCacheItem[itemmax]; 47 WearableCacheItem[] retitems = new WearableCacheItem[itemmax];
48 for (uint i=0;i<itemmax;i++) 48 for (uint i=0;i<itemmax;i++)
49 retitems[i] = new WearableCacheItem() {CacheId = UUID.Zero, TextureID = UUID.Zero, TextureIndex = i + 1}; 49 retitems[i] = new WearableCacheItem() {CacheId = UUID.Zero, TextureID = UUID.Zero, TextureIndex = i};
50 return retitems; 50 return retitems;
51 } 51 }
52
52 public static WearableCacheItem[] FromOSD(OSD pInput, IImprovedAssetCache dataCache) 53 public static WearableCacheItem[] FromOSD(OSD pInput, IImprovedAssetCache dataCache)
53 { 54 {
54 List<WearableCacheItem> ret = new List<WearableCacheItem>(); 55 List<WearableCacheItem> ret = new List<WearableCacheItem>();
@@ -98,6 +99,7 @@ namespace OpenSim.Framework
98 return ret.ToArray(); 99 return ret.ToArray();
99 100
100 } 101 }
102
101 public static OSD ToOSD(WearableCacheItem[] pcacheItems, IImprovedAssetCache dataCache) 103 public static OSD ToOSD(WearableCacheItem[] pcacheItems, IImprovedAssetCache dataCache)
102 { 104 {
103 OSDArray arr = new OSDArray(); 105 OSDArray arr = new OSDArray();
@@ -124,6 +126,68 @@ namespace OpenSim.Framework
124 } 126 }
125 return arr; 127 return arr;
126 } 128 }
129
130 public static OSDArray BakedToOSD(WearableCacheItem[] pcacheItems)
131 {
132 if (pcacheItems.Length < AvatarAppearance.BAKE_INDICES[AvatarAppearance.BAKE_INDICES.Length - 1])
133 return null;
134
135 OSDArray arr = new OSDArray();
136
137 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
138 {
139 int idx = AvatarAppearance.BAKE_INDICES[i];
140
141 WearableCacheItem item = pcacheItems[idx];
142
143 OSDMap itemmap = new OSDMap();
144 itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex));
145 itemmap.Add("cacheid", OSD.FromUUID(item.CacheId));
146 itemmap.Add("textureid", OSD.FromUUID(item.TextureID));
147/*
148 if (item.TextureAsset != null)
149 {
150 itemmap.Add("assetdata", OSD.FromBinary(item.TextureAsset.Data));
151 itemmap.Add("assetcreator", OSD.FromString(item.TextureAsset.CreatorID));
152 itemmap.Add("assetname", OSD.FromString(item.TextureAsset.Name));
153 }
154 */
155 arr.Add(itemmap);
156 }
157 return arr;
158 }
159
160 public static WearableCacheItem[] BakedFromOSD(OSD pInput)
161 {
162 WearableCacheItem[] pcache = WearableCacheItem.GetDefaultCacheItem();
163
164 if (pInput.Type == OSDType.Array)
165 {
166 OSDArray itemarray = (OSDArray)pInput;
167 foreach (OSDMap item in itemarray)
168 {
169 int idx = (int)item["textureindex"].AsUInteger();
170 if (idx < 0 || idx > pcache.Length)
171 continue;
172 pcache[idx].CacheId = item["cacheid"].AsUUID();
173 pcache[idx].TextureID = item["textureid"].AsUUID();
174/*
175 if (item.ContainsKey("assetdata"))
176 {
177 AssetBase asset = new AssetBase(item["textureid"].AsUUID(), "BakedTexture", (sbyte)AssetType.Texture, UUID.Zero.ToString());
178 asset.Temporary = true;
179 asset.Local = true;
180 asset.Data = item["assetdata"].AsBinary();
181 pcache[idx].TextureAsset = asset;
182 }
183 else
184 */
185 pcache[idx].TextureAsset = null;
186 }
187 }
188 return pcache;
189 }
190
127 public static WearableCacheItem SearchTextureIndex(uint pTextureIndex,WearableCacheItem[] pcacheItems) 191 public static WearableCacheItem SearchTextureIndex(uint pTextureIndex,WearableCacheItem[] pcacheItems)
128 { 192 {
129 for (int i = 0; i < pcacheItems.Length; i++) 193 for (int i = 0; i < pcacheItems.Length; i++)
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index b180c8a..3436984 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -233,6 +233,9 @@ namespace OpenSim.Framework
233 string errorMessage = "unknown error"; 233 string errorMessage = "unknown error";
234 int tickstart = Util.EnvironmentTickCount(); 234 int tickstart = Util.EnvironmentTickCount();
235 int tickdata = 0; 235 int tickdata = 0;
236 int tickcompressdata = 0;
237 int tickJsondata = 0;
238 int compsize = 0;
236 string strBuffer = null; 239 string strBuffer = null;
237 240
238 try 241 try
@@ -250,6 +253,8 @@ namespace OpenSim.Framework
250 { 253 {
251 strBuffer = OSDParser.SerializeJsonString(data); 254 strBuffer = OSDParser.SerializeJsonString(data);
252 255
256 tickJsondata = Util.EnvironmentTickCountSubtract(tickstart);
257
253 if (DebugLevel >= 5) 258 if (DebugLevel >= 5)
254 LogOutgoingDetail("SEND", reqnum, strBuffer); 259 LogOutgoingDetail("SEND", reqnum, strBuffer);
255 260
@@ -271,13 +276,20 @@ namespace OpenSim.Framework
271 // gets written on the stream upon Dispose() 276 // gets written on the stream upon Dispose()
272 } 277 }
273 byte[] buf = ms.ToArray(); 278 byte[] buf = ms.ToArray();
279
280 tickcompressdata = Util.EnvironmentTickCountSubtract(tickstart);
281
274 request.ContentLength = buf.Length; //Count bytes to send 282 request.ContentLength = buf.Length; //Count bytes to send
283 compsize = buf.Length;
275 using (Stream requestStream = request.GetRequestStream()) 284 using (Stream requestStream = request.GetRequestStream())
276 requestStream.Write(buf, 0, (int)buf.Length); 285 requestStream.Write(buf, 0, (int)buf.Length);
277 } 286 }
278 } 287 }
279 else 288 else
280 { 289 {
290 tickcompressdata = tickJsondata;
291 compsize = buffer.Length;
292
281 request.ContentLength = buffer.Length; //Count bytes to send 293 request.ContentLength = buffer.Length; //Count bytes to send
282 using (Stream requestStream = request.GetRequestStream()) 294 using (Stream requestStream = request.GetRequestStream())
283 requestStream.Write(buffer, 0, buffer.Length); //Send it 295 requestStream.Write(buffer, 0, buffer.Length); //Send it
@@ -314,6 +326,7 @@ namespace OpenSim.Framework
314 catch (Exception ex) 326 catch (Exception ex)
315 { 327 {
316 errorMessage = ex.Message; 328 errorMessage = ex.Message;
329 m_log.Debug("[WEB UTIL]: Exception making request: " + ex.ToString());
317 } 330 }
318 finally 331 finally
319 { 332 {
@@ -321,8 +334,17 @@ namespace OpenSim.Framework
321 if (tickdiff > LongCallTime) 334 if (tickdiff > LongCallTime)
322 { 335 {
323 m_log.InfoFormat( 336 m_log.InfoFormat(
324 "[LOGHTTP]: Slow JSON-RPC request {0} {1} to {2} took {3}ms, {4}ms writing, {5}", 337 "[WEB UTIL]: Slow ServiceOSD request {0} {1} {2} took {3}ms, {4}ms writing({5} at Json; {6} at comp), {7} bytes ({8} uncomp): {9}",
325 reqnum, method, url, tickdiff, tickdata, 338 reqnum,
339 method,
340 url,
341 tickdiff,
342 tickdata,
343 tickJsondata,
344 tickcompressdata,
345 compsize,
346 strBuffer != null ? strBuffer.Length : 0,
347
326 strBuffer != null 348 strBuffer != null
327 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer) 349 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
328 : ""); 350 : "");
@@ -396,7 +418,7 @@ namespace OpenSim.Framework
396 /// </summary> 418 /// </summary>
397 public static OSDMap PostToService(string url, NameValueCollection data) 419 public static OSDMap PostToService(string url, NameValueCollection data)
398 { 420 {
399 return ServiceFormRequest(url,data,10000); 421 return ServiceFormRequest(url,data, 30000);
400 } 422 }
401 423
402 public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout) 424 public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout)
@@ -779,6 +801,20 @@ namespace OpenSim.Framework
779 MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, action, maxConnections, null); 801 MakeRequest<TRequest, TResponse>(verb, requestUrl, obj, action, maxConnections, null);
780 } 802 }
781 803
804 /// <summary>
805 /// Perform a synchronous REST request.
806 /// </summary>
807 /// <param name="verb"></param>
808 /// <param name="requestUrl"></param>
809 /// <param name="obj"></param>
810 /// <param name="pTimeout">
811 /// Request timeout in seconds. Timeout.Infinite indicates no timeout. If 0 is passed then the default HttpWebRequest timeout is used (100 seconds)
812 /// </param>
813 /// <param name="maxConnections"></param>
814 /// <returns>
815 /// The response. If there was an internal exception or the request timed out,
816 /// then the default(TResponse) is returned.
817 /// </returns>
782 public static void MakeRequest<TRequest, TResponse>(string verb, 818 public static void MakeRequest<TRequest, TResponse>(string verb,
783 string requestUrl, TRequest obj, Action<TResponse> action, 819 string requestUrl, TRequest obj, Action<TResponse> action,
784 int maxConnections, IServiceAuth auth) 820 int maxConnections, IServiceAuth auth)
@@ -791,6 +827,7 @@ namespace OpenSim.Framework
791 827
792 int tickstart = Util.EnvironmentTickCount(); 828 int tickstart = Util.EnvironmentTickCount();
793 int tickdata = 0; 829 int tickdata = 0;
830 int tickdiff = 0;
794 831
795 Type type = typeof(TRequest); 832 Type type = typeof(TRequest);
796 833
@@ -936,7 +973,7 @@ namespace OpenSim.Framework
936 }, null); 973 }, null);
937 } 974 }
938 975
939 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 976 tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
940 if (tickdiff > WebUtil.LongCallTime) 977 if (tickdiff > WebUtil.LongCallTime)
941 { 978 {
942 string originalRequest = null; 979 string originalRequest = null;
@@ -948,8 +985,7 @@ namespace OpenSim.Framework
948 if (originalRequest.Length > WebUtil.MaxRequestDiagLength) 985 if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
949 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength); 986 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
950 } 987 }
951 988 m_log.InfoFormat(
952 m_log.InfoFormat(
953 "[LOGHTTP]: Slow AsynchronousRequestObject request {0} {1} to {2} took {3}ms, {4}ms writing, {5}", 989 "[LOGHTTP]: Slow AsynchronousRequestObject request {0} {1} to {2} took {3}ms, {4}ms writing, {5}",
954 reqnum, verb, requestUrl, tickdiff, tickdata, 990 reqnum, verb, requestUrl, tickdiff, tickdata,
955 originalRequest); 991 originalRequest);
@@ -957,6 +993,7 @@ namespace OpenSim.Framework
957 else if (WebUtil.DebugLevel >= 4) 993 else if (WebUtil.DebugLevel >= 4)
958 { 994 {
959 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms, {2}ms writing", 995 m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} took {1}ms, {2}ms writing",
996
960 reqnum, tickdiff, tickdata); 997 reqnum, tickdiff, tickdata);
961 } 998 }
962 } 999 }
@@ -1004,6 +1041,8 @@ namespace OpenSim.Framework
1004 1041
1005 string respstring = String.Empty; 1042 string respstring = String.Empty;
1006 1043
1044 int tickset = Util.EnvironmentTickCountSubtract(tickstart);
1045
1007 using (MemoryStream buffer = new MemoryStream()) 1046 using (MemoryStream buffer = new MemoryStream())
1008 { 1047 {
1009 if ((verb == "POST") || (verb == "PUT")) 1048 if ((verb == "POST") || (verb == "PUT"))
@@ -1070,8 +1109,13 @@ namespace OpenSim.Framework
1070 if (tickdiff > WebUtil.LongCallTime) 1109 if (tickdiff > WebUtil.LongCallTime)
1071 { 1110 {
1072 m_log.InfoFormat( 1111 m_log.InfoFormat(
1073 "[LOGHTTP]: Slow SynchronousRestForms request {0} {1} to {2} took {3}ms, {4}ms writing, {5}", 1112 "[FORMS]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
1074 reqnum, verb, requestUrl, tickdiff, tickdata, 1113 reqnum,
1114 verb,
1115 requestUrl,
1116 tickdiff,
1117 tickset,
1118 tickdata,
1075 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj); 1119 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
1076 } 1120 }
1077 else if (WebUtil.DebugLevel >= 4) 1121 else if (WebUtil.DebugLevel >= 4)
@@ -1202,7 +1246,7 @@ namespace OpenSim.Framework
1202 auth.AddAuthorization(ht.Headers); 1246 auth.AddAuthorization(ht.Headers);
1203 1247
1204 if (pTimeout != 0) 1248 if (pTimeout != 0)
1205 ht.Timeout = pTimeout; 1249 request.Timeout = pTimeout;
1206 1250
1207 if (maxConnections > 0 && ht.ServicePoint.ConnectionLimit < maxConnections) 1251 if (maxConnections > 0 && ht.ServicePoint.ConnectionLimit < maxConnections)
1208 ht.ServicePoint.ConnectionLimit = maxConnections; 1252 ht.ServicePoint.ConnectionLimit = maxConnections;
@@ -1343,7 +1387,6 @@ namespace OpenSim.Framework
1343 1387
1344 return deserial; 1388 return deserial;
1345 } 1389 }
1346
1347 1390
1348 public static class XMLResponseHelper 1391 public static class XMLResponseHelper
1349 { 1392 {
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs
index bf34419..e441cc8 100644
--- a/OpenSim/Region/Application/Application.cs
+++ b/OpenSim/Region/Application/Application.cs
@@ -75,6 +75,7 @@ namespace OpenSim
75 new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 75 new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
76 76
77 ServicePointManager.DefaultConnectionLimit = 12; 77 ServicePointManager.DefaultConnectionLimit = 12;
78 ServicePointManager.UseNagleAlgorithm = false;
78 79
79 // Add the arguments supplied when running the application to the configuration 80 // Add the arguments supplied when running the application to the configuration
80 ArgvConfigSource configSource = new ArgvConfigSource(args); 81 ArgvConfigSource configSource = new ArgvConfigSource(args);
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 5af8194..a2ba8c0 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -114,8 +114,8 @@ namespace OpenSim
114 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) 114 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
115 Util.FireAndForgetMethod = asyncCallMethod; 115 Util.FireAndForgetMethod = asyncCallMethod;
116 116
117 stpMinThreads = startupConfig.GetInt("MinPoolThreads", 15); 117 stpMinThreads = startupConfig.GetInt("MinPoolThreads", 2 );
118 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 300); 118 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 25);
119 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) "); 119 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) ");
120 } 120 }
121 121
@@ -272,7 +272,7 @@ namespace OpenSim
272 + " [--force-terrain] [--force-parcels]" 272 + " [--force-terrain] [--force-parcels]"
273 + " [--no-objects]" 273 + " [--no-objects]"
274 + " [--rotation degrees] [--rotation-center \"<x,y,z>\"]" 274 + " [--rotation degrees] [--rotation-center \"<x,y,z>\"]"
275 + " [--displacement \"<x,y,z>\"]" 275 + " [--displacement \"<x,y,z>\"]"
276 + " [<OAR path>]", 276 + " [<OAR path>]",
277 "Load a region's data from an OAR archive.", 277 "Load a region's data from an OAR archive.",
278 "--merge will merge the OAR with the existing scene (suppresses terrain and parcel info loading).\n" 278 "--merge will merge the OAR with the existing scene (suppresses terrain and parcel info loading).\n"
@@ -500,7 +500,7 @@ namespace OpenSim
500 if (alert != null) 500 if (alert != null)
501 presence.ControllingClient.Kick(alert); 501 presence.ControllingClient.Kick(alert);
502 else 502 else
503 presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); 503 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
504 504
505 presence.Scene.CloseAgent(presence.UUID, force); 505 presence.Scene.CloseAgent(presence.UUID, force);
506 break; 506 break;
@@ -1028,15 +1028,25 @@ namespace OpenSim
1028 cdt.AddColumn("Circuit code", 12); 1028 cdt.AddColumn("Circuit code", 12);
1029 cdt.AddColumn("Endpoint", 23); 1029 cdt.AddColumn("Endpoint", 23);
1030 cdt.AddColumn("Active?", 7); 1030 cdt.AddColumn("Active?", 7);
1031 cdt.AddColumn("ChildAgent?", 7);
1032 cdt.AddColumn("ping(ms)", 8);
1031 1033
1032 SceneManager.ForEachScene( 1034 SceneManager.ForEachScene(
1033 s => s.ForEachClient( 1035 s => s.ForEachClient(
1034 c => cdt.AddRow( 1036 c =>
1035 s.Name, 1037 {
1036 c.Name, 1038 bool child = false;
1037 c.CircuitCode.ToString(), 1039 if(c.SceneAgent != null && c.SceneAgent.IsChildAgent)
1038 c.RemoteEndPoint.ToString(), 1040 child = true;
1039 c.IsActive.ToString()))); 1041 cdt.AddRow(
1042 s.Name,
1043 c.Name,
1044 c.CircuitCode.ToString(),
1045 c.RemoteEndPoint.ToString(),
1046 c.IsActive.ToString(),
1047 child.ToString(),
1048 c.PingTimeMS);
1049 }));
1040 1050
1041 MainConsole.Instance.Output(cdt.ToString()); 1051 MainConsole.Instance.Output(cdt.ToString());
1042 } 1052 }
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index ab6f036..41966ff 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -110,6 +110,10 @@ namespace OpenSim
110 110
111 public List<IApplicationPlugin> m_plugins = new List<IApplicationPlugin>(); 111 public List<IApplicationPlugin> m_plugins = new List<IApplicationPlugin>();
112 112
113 private List<string> m_permsModules;
114
115 private bool m_securePermissionsLoading = true;
116
113 /// <value> 117 /// <value>
114 /// The config information passed into the OpenSimulator region server. 118 /// The config information passed into the OpenSimulator region server.
115 /// </value> 119 /// </value>
@@ -219,6 +223,14 @@ namespace OpenSim
219 CreatePIDFile(pidFile); 223 CreatePIDFile(pidFile);
220 224
221 userStatsURI = startupConfig.GetString("Stats_URI", String.Empty); 225 userStatsURI = startupConfig.GetString("Stats_URI", String.Empty);
226
227 m_securePermissionsLoading = startupConfig.GetBoolean("SecurePermissionsLoading", true);
228
229 string permissionModules = Util.GetConfigVarFromSections<string>(Config, "permissionmodules",
230 new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule");
231
232 m_permsModules = new List<string>(permissionModules.Split(','));
233
222 managedStatsURI = startupConfig.GetString("ManagedStatsRemoteFetchURI", String.Empty); 234 managedStatsURI = startupConfig.GetString("ManagedStatsRemoteFetchURI", String.Empty);
223 } 235 }
224 236
@@ -410,7 +422,32 @@ namespace OpenSim
410 } 422 }
411 else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing..."); 423 else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing...");
412 424
425 if (m_securePermissionsLoading)
426 {
427 foreach (string s in m_permsModules)
428 {
429 if (!scene.RegionModules.ContainsKey(s))
430 {
431 m_log.Fatal("[MODULES]: Required module " + s + " not found.");
432 Environment.Exit(0);
433 }
434 }
435
436 m_log.InfoFormat("[SCENE]: Secure permissions loading enabled, modules loaded: {0}", String.Join(" ", m_permsModules.ToArray()));
437 }
438
413 scene.SetModuleInterfaces(); 439 scene.SetModuleInterfaces();
440// First Step of bootreport sequence
441 if (scene.SnmpService != null)
442 {
443 scene.SnmpService.ColdStart(1,scene);
444 scene.SnmpService.LinkDown(scene);
445 }
446
447 if (scene.SnmpService != null)
448 {
449 scene.SnmpService.BootInfo("Loading prins", scene);
450 }
414 451
415 while (regionInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null) 452 while (regionInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null)
416 SetUpEstateOwner(scene); 453 SetUpEstateOwner(scene);
@@ -424,6 +461,11 @@ namespace OpenSim
424 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); 461 scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID);
425 scene.EventManager.TriggerParcelPrimCountUpdate(); 462 scene.EventManager.TriggerParcelPrimCountUpdate();
426 463
464 if (scene.SnmpService != null)
465 {
466 scene.SnmpService.BootInfo("Grid Registration in progress", scene);
467 }
468
427 try 469 try
428 { 470 {
429 scene.RegisterRegionWithGrid(); 471 scene.RegisterRegionWithGrid();
@@ -434,15 +476,29 @@ namespace OpenSim
434 "[STARTUP]: Registration of region with grid failed, aborting startup due to {0} {1}", 476 "[STARTUP]: Registration of region with grid failed, aborting startup due to {0} {1}",
435 e.Message, e.StackTrace); 477 e.Message, e.StackTrace);
436 478
479 if (scene.SnmpService != null)
480 {
481 scene.SnmpService.Critical("Grid registration failed. Startup aborted.", scene);
482 }
437 // Carrying on now causes a lot of confusion down the 483 // Carrying on now causes a lot of confusion down the
438 // line - we need to get the user's attention 484 // line - we need to get the user's attention
439 Environment.Exit(1); 485 Environment.Exit(1);
440 } 486 }
441 487
488 if (scene.SnmpService != null)
489 {
490 scene.SnmpService.BootInfo("Grid Registration done", scene);
491 }
492
442 // We need to do this after we've initialized the 493 // We need to do this after we've initialized the
443 // scripting engines. 494 // scripting engines.
444 scene.CreateScriptInstances(); 495 scene.CreateScriptInstances();
445 496
497 if (scene.SnmpService != null)
498 {
499 scene.SnmpService.BootInfo("ScriptEngine started", scene);
500 }
501
446 SceneManager.Add(scene); 502 SceneManager.Add(scene);
447 503
448 //if (m_autoCreateClientStack) 504 //if (m_autoCreateClientStack)
@@ -454,10 +510,20 @@ namespace OpenSim
454 // } 510 // }
455 //} 511 //}
456 512
513 if (scene.SnmpService != null)
514 {
515 scene.SnmpService.BootInfo("Initializing region modules", scene);
516 }
457 scene.EventManager.OnShutdown += delegate() { ShutdownRegion(scene); }; 517 scene.EventManager.OnShutdown += delegate() { ShutdownRegion(scene); };
458 518
459 mscene = scene; 519 mscene = scene;
460 520
521 if (scene.SnmpService != null)
522 {
523 scene.SnmpService.BootInfo("The region is operational", scene);
524 scene.SnmpService.LinkUp(scene);
525 }
526
461 //return clientServers; 527 //return clientServers;
462 } 528 }
463 529
@@ -573,6 +639,11 @@ namespace OpenSim
573 private void ShutdownRegion(Scene scene) 639 private void ShutdownRegion(Scene scene)
574 { 640 {
575 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName); 641 m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName);
642 if (scene.SnmpService != null)
643 {
644 scene.SnmpService.BootInfo("The region is shutting down", scene);
645 scene.SnmpService.LinkDown(scene);
646 }
576 IRegionModulesController controller; 647 IRegionModulesController controller;
577 if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller)) 648 if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller))
578 { 649 {
diff --git a/OpenSim/Region/Application/RegionApplicationBase.cs b/OpenSim/Region/Application/RegionApplicationBase.cs
index 08c8579..ba92fd6 100644
--- a/OpenSim/Region/Application/RegionApplicationBase.cs
+++ b/OpenSim/Region/Application/RegionApplicationBase.cs
@@ -87,17 +87,29 @@ namespace OpenSim
87 // "OOB" Server 87 // "OOB" Server
88 if (m_networkServersInfo.ssl_listener) 88 if (m_networkServersInfo.ssl_listener)
89 { 89 {
90 BaseHttpServer server = new BaseHttpServer( 90 if (!m_networkServersInfo.ssl_external)
91 m_networkServersInfo.https_port, m_networkServersInfo.ssl_listener, m_networkServersInfo.cert_path, 91 {
92 m_networkServersInfo.cert_pass); 92 BaseHttpServer server = new BaseHttpServer(
93 m_networkServersInfo.https_port, m_networkServersInfo.ssl_listener, m_networkServersInfo.cert_path,
94 m_networkServersInfo.cert_pass);
93 95
94 m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port); 96 m_log.InfoFormat("[REGION SERVER]: Starting HTTPS server on port {0}", server.Port);
95 MainServer.AddHttpServer(server); 97 MainServer.AddHttpServer(server);
96 server.Start(); 98 server.Start();
99 }
100 else
101 {
102 BaseHttpServer server = new BaseHttpServer(
103 m_networkServersInfo.https_port);
104
105 m_log.InfoFormat("[REGION SERVER]: Starting HTTP server on port {0} for external HTTPS", server.Port);
106 MainServer.AddHttpServer(server);
107 server.Start();
108 }
97 } 109 }
98 110
99 base.StartupSpecific(); 111 base.StartupSpecific();
100 } 112 }
101 113
102 } 114 }
103} \ No newline at end of file 115}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 774202e..1236e83 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Timers;
29using System.Collections; 30using System.Collections;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.IO; 32using System.IO;
@@ -44,7 +45,6 @@ using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Scenes.Serialization; 45using OpenSim.Region.Framework.Scenes.Serialization;
45using OpenSim.Framework.Servers; 46using OpenSim.Framework.Servers;
46using OpenSim.Framework.Servers.HttpServer; 47using OpenSim.Framework.Servers.HttpServer;
47using OpenSim.Framework.Client;
48using OpenSim.Services.Interfaces; 48using OpenSim.Services.Interfaces;
49 49
50using Caps = OpenSim.Framework.Capabilities.Caps; 50using Caps = OpenSim.Framework.Capabilities.Caps;
@@ -55,14 +55,16 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
55namespace OpenSim.Region.ClientStack.Linden 55namespace OpenSim.Region.ClientStack.Linden
56{ 56{
57 public delegate void UpLoadedAsset( 57 public delegate void UpLoadedAsset(
58 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, 58 string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder,
59 byte[] data, string inventoryType, string assetType); 59 byte[] data, string inventoryType, string assetType,
60 int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
61 bool IsAtestUpload, ref string error);
60 62
61 public delegate UUID UpdateItem(UUID itemID, byte[] data); 63 public delegate UUID UpdateItem(UUID itemID, byte[] data);
62 64
63 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); 65 public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
64 66
65 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); 67 public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost);
66 68
67 public delegate void NewAsset(AssetBase asset); 69 public delegate void NewAsset(AssetBase asset);
68 70
@@ -88,6 +90,7 @@ namespace OpenSim.Region.ClientStack.Linden
88 90
89 private Scene m_Scene; 91 private Scene m_Scene;
90 private Caps m_HostCapsObj; 92 private Caps m_HostCapsObj;
93 private ModelCost m_ModelCost;
91 94
92 private static readonly string m_requestPath = "0000/"; 95 private static readonly string m_requestPath = "0000/";
93 // private static readonly string m_mapLayerPath = "0001/"; 96 // private static readonly string m_mapLayerPath = "0001/";
@@ -99,8 +102,10 @@ namespace OpenSim.Region.ClientStack.Linden
99 private static readonly string m_copyFromNotecardPath = "0007/"; 102 private static readonly string m_copyFromNotecardPath = "0007/";
100 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. 103 // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule.
101 private static readonly string m_getObjectPhysicsDataPath = "0101/"; 104 private static readonly string m_getObjectPhysicsDataPath = "0101/";
102 /* 0102 - 0103 RESERVED */ 105 private static readonly string m_getObjectCostPath = "0102/";
106 private static readonly string m_ResourceCostSelectedPath = "0103/";
103 private static readonly string m_UpdateAgentInformationPath = "0500/"; 107 private static readonly string m_UpdateAgentInformationPath = "0500/";
108 private static readonly string m_animSetTaskUpdatePath = "0260/";
104 109
105 // These are callbacks which will be setup by the scene so that we can update scene data when we 110 // These are callbacks which will be setup by the scene so that we can update scene data when we
106 // receive capability calls 111 // receive capability calls
@@ -115,12 +120,50 @@ namespace OpenSim.Region.ClientStack.Linden
115 private IAssetService m_assetService; 120 private IAssetService m_assetService;
116 private bool m_dumpAssetsToFile = false; 121 private bool m_dumpAssetsToFile = false;
117 private string m_regionName; 122 private string m_regionName;
123
118 private int m_levelUpload = 0; 124 private int m_levelUpload = 0;
119 125
126 private bool m_enableFreeTestUpload = false; // allows "TEST-" prefix hack
127 private bool m_ForceFreeTestUpload = false; // forces all uploads to be test
128
129 private bool m_enableModelUploadTextureToInventory = false; // place uploaded textures also in inventory
130 // may not be visible till relog
131
132 private bool m_RestrictFreeTestUploadPerms = false; // reduces also the permitions. Needs a creator defined!!
133 private UUID m_testAssetsCreatorID = UUID.Zero;
134
135 private float m_PrimScaleMin = 0.001f;
136
137 private enum FileAgentInventoryState : int
138 {
139 idle = 0,
140 processRequest = 1,
141 waitUpload = 2,
142 processUpload = 3
143 }
144 private FileAgentInventoryState m_FileAgentInventoryState = FileAgentInventoryState.idle;
145
120 public BunchOfCaps(Scene scene, Caps caps) 146 public BunchOfCaps(Scene scene, Caps caps)
121 { 147 {
122 m_Scene = scene; 148 m_Scene = scene;
123 m_HostCapsObj = caps; 149 m_HostCapsObj = caps;
150
151 // create a model upload cost provider
152 m_ModelCost = new ModelCost();
153 // tell it about scene object limits
154 m_ModelCost.NonPhysicalPrimScaleMax = m_Scene.m_maxNonphys;
155 m_ModelCost.PhysicalPrimScaleMax = m_Scene.m_maxPhys;
156
157// m_ModelCost.ObjectLinkedPartsMax = ??
158// m_ModelCost.PrimScaleMin = ??
159
160 m_PrimScaleMin = m_ModelCost.PrimScaleMin;
161 float modelTextureUploadFactor = m_ModelCost.ModelTextureCostFactor;
162 float modelUploadFactor = m_ModelCost.ModelMeshCostFactor;
163 float modelMinUploadCostFactor = m_ModelCost.ModelMinCostFactor;
164 float modelPrimCreationCost = m_ModelCost.primCreationCost;
165 float modelMeshByteCost = m_ModelCost.bytecost;
166
124 IConfigSource config = m_Scene.Config; 167 IConfigSource config = m_Scene.Config;
125 if (config != null) 168 if (config != null)
126 { 169 {
@@ -135,6 +178,37 @@ namespace OpenSim.Region.ClientStack.Linden
135 { 178 {
136 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 179 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
137 } 180 }
181 // economy for model upload
182 IConfig EconomyConfig = config.Configs["Economy"];
183 if (EconomyConfig != null)
184 {
185 modelUploadFactor = EconomyConfig.GetFloat("MeshModelUploadCostFactor", modelUploadFactor);
186 modelTextureUploadFactor = EconomyConfig.GetFloat("MeshModelUploadTextureCostFactor", modelTextureUploadFactor);
187 modelMinUploadCostFactor = EconomyConfig.GetFloat("MeshModelMinCostFactor", modelMinUploadCostFactor);
188 // next 2 are normalized so final cost is afected by modelUploadFactor above and normal cost
189 modelPrimCreationCost = EconomyConfig.GetFloat("ModelPrimCreationCost", modelPrimCreationCost);
190 modelMeshByteCost = EconomyConfig.GetFloat("ModelMeshByteCost", modelMeshByteCost);
191
192 m_enableModelUploadTextureToInventory = EconomyConfig.GetBoolean("MeshModelAllowTextureToInventory", m_enableModelUploadTextureToInventory);
193
194 m_RestrictFreeTestUploadPerms = EconomyConfig.GetBoolean("m_RestrictFreeTestUploadPerms", m_RestrictFreeTestUploadPerms);
195 m_enableFreeTestUpload = EconomyConfig.GetBoolean("AllowFreeTestUpload", m_enableFreeTestUpload);
196 m_ForceFreeTestUpload = EconomyConfig.GetBoolean("ForceFreeTestUpload", m_ForceFreeTestUpload);
197 string testcreator = EconomyConfig.GetString("TestAssetsCreatorID", "");
198 if (testcreator != "")
199 {
200 UUID id;
201 UUID.TryParse(testcreator, out id);
202 if (id != null)
203 m_testAssetsCreatorID = id;
204 }
205
206 m_ModelCost.ModelMeshCostFactor = modelUploadFactor;
207 m_ModelCost.ModelTextureCostFactor = modelTextureUploadFactor;
208 m_ModelCost.ModelMinCostFactor = modelMinUploadCostFactor;
209 m_ModelCost.primCreationCost = modelPrimCreationCost;
210 m_ModelCost.bytecost = modelMeshByteCost;
211 }
138 } 212 }
139 213
140 m_assetService = m_Scene.AssetService; 214 m_assetService = m_Scene.AssetService;
@@ -146,6 +220,8 @@ namespace OpenSim.Region.ClientStack.Linden
146 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset; 220 ItemUpdatedCall = m_Scene.CapsUpdateInventoryItemAsset;
147 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset; 221 TaskScriptUpdatedCall = m_Scene.CapsUpdateTaskInventoryScriptAsset;
148 GetClient = m_Scene.SceneGraph.GetControllingClient; 222 GetClient = m_Scene.SceneGraph.GetControllingClient;
223
224 m_FileAgentInventoryState = FileAgentInventoryState.idle;
149 } 225 }
150 226
151 /// <summary> 227 /// <summary>
@@ -173,13 +249,31 @@ namespace OpenSim.Region.ClientStack.Linden
173 //m_capsHandlers["MapLayer"] = 249 //m_capsHandlers["MapLayer"] =
174 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 250 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
175 // capsBase + m_mapLayerPath, 251 // capsBase + m_mapLayerPath,
176 // GetMapLayer); 252 // GetMapLayer);
253
254 IRequestHandler getObjectPhysicsDataHandler
255 = new RestStreamHandler(
256 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
257 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
258
259 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
260 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
261 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
262 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
263
264
177 IRequestHandler req 265 IRequestHandler req
178 = new RestStreamHandler( 266 = new RestStreamHandler(
179 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null); 267 "POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory, "UpdateScript", null);
180 268
181 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req); 269 m_HostCapsObj.RegisterHandler("UpdateScriptTaskInventory", req);
182 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req); 270 m_HostCapsObj.RegisterHandler("UpdateScriptTask", req);
271
272// IRequestHandler animSetRequestHandler
273// = new RestStreamHandler(
274// "POST", capsBase + m_animSetTaskUpdatePath, AnimSetTaskInventory, "UpdateScript", null);
275
276// m_HostCapsObj.RegisterHandler("UpdateAnimSetTaskInventory", animSetRequestHandler);
183 } 277 }
184 catch (Exception e) 278 catch (Exception e)
185 { 279 {
@@ -191,7 +285,6 @@ namespace OpenSim.Region.ClientStack.Linden
191 { 285 {
192 try 286 try
193 { 287 {
194 // I don't think this one works...
195 m_HostCapsObj.RegisterHandler( 288 m_HostCapsObj.RegisterHandler(
196 "NewFileAgentInventory", 289 "NewFileAgentInventory",
197 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>( 290 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDAssetUploadResponse>(
@@ -206,13 +299,11 @@ namespace OpenSim.Region.ClientStack.Linden
206 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null); 299 "POST", capsBase + m_notecardUpdatePath, NoteCardAgentInventory, "Update*", null);
207 300
208 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 301 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
302 m_HostCapsObj.RegisterHandler("UpdateAnimSetAgentInventory", req);
209 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 303 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
210 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 304 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
211 305
212 IRequestHandler getObjectPhysicsDataHandler 306
213 = new RestStreamHandler(
214 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
215 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
216 307
217 IRequestHandler UpdateAgentInformationHandler 308 IRequestHandler UpdateAgentInformationHandler
218 = new RestStreamHandler( 309 = new RestStreamHandler(
@@ -268,8 +359,11 @@ namespace OpenSim.Region.ClientStack.Linden
268 public string SeedCapRequest(string request, string path, string param, 359 public string SeedCapRequest(string request, string path, string param,
269 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 360 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
270 { 361 {
271// m_log.DebugFormat( 362 m_log.DebugFormat(
272// "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); 363 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
364
365 if (!m_HostCapsObj.WaitForActivation())
366 return string.Empty;
273 367
274 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 368 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
275 { 369 {
@@ -400,62 +494,178 @@ namespace OpenSim.Region.ClientStack.Linden
400 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString()); 494 //m_log.Debug("[CAPS]: NewAgentInventoryRequest Request is: " + llsdRequest.ToString());
401 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type); 495 //m_log.Debug("asset upload request via CAPS" + llsdRequest.inventory_type + " , " + llsdRequest.asset_type);
402 496
497 // start by getting the client
498 IClientAPI client = null;
499 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
500
501 // check current state so we only have one service at a time
502 lock (m_ModelCost)
503 {
504 switch (m_FileAgentInventoryState)
505 {
506 case FileAgentInventoryState.processRequest:
507 case FileAgentInventoryState.processUpload:
508 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
509 resperror.message = "Uploader busy processing previus request";
510 resperror.identifier = UUID.Zero;
511
512 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
513 errorResponse.uploader = "";
514 errorResponse.state = "error";
515 errorResponse.error = resperror;
516 return errorResponse;
517 break;
518 case FileAgentInventoryState.waitUpload:
519 // todo stop current uploader server
520 break;
521 case FileAgentInventoryState.idle:
522 default:
523 break;
524 }
525
526 m_FileAgentInventoryState = FileAgentInventoryState.processRequest;
527 }
528
529 int cost = 0;
530 int nreqtextures = 0;
531 int nreqmeshs= 0;
532 int nreqinstances = 0;
533 bool IsAtestUpload = false;
534
535 string assetName = llsdRequest.name;
536
537 LLSDAssetUploadResponseData meshcostdata = new LLSDAssetUploadResponseData();
538
403 if (llsdRequest.asset_type == "texture" || 539 if (llsdRequest.asset_type == "texture" ||
404 llsdRequest.asset_type == "animation" || 540 llsdRequest.asset_type == "animation" ||
541 llsdRequest.asset_type == "animatn" || // this is the asset name actually used by viewers
542 llsdRequest.asset_type == "mesh" ||
405 llsdRequest.asset_type == "sound") 543 llsdRequest.asset_type == "sound")
406 { 544 {
407 ScenePresence avatar = null; 545 ScenePresence avatar = null;
408 IClientAPI client = null;
409 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 546 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar);
410 547
411 // check user level 548 // check user level
412 if (avatar != null) 549 if (avatar != null)
413 { 550 {
414 client = avatar.ControllingClient;
415
416 if (avatar.UserLevel < m_levelUpload) 551 if (avatar.UserLevel < m_levelUpload)
417 { 552 {
418 if (client != null) 553 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
419 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false); 554 resperror.message = "Insufficient permissions to upload";
555 resperror.identifier = UUID.Zero;
420 556
421 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 557 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
422 errorResponse.uploader = ""; 558 errorResponse.uploader = "";
423 errorResponse.state = "error"; 559 errorResponse.state = "error";
560 errorResponse.error = resperror;
561 lock (m_ModelCost)
562 m_FileAgentInventoryState = FileAgentInventoryState.idle;
424 return errorResponse; 563 return errorResponse;
425 } 564 }
426 } 565 }
427 566
428 // check funds 567 // check test upload and funds
429 if (client != null) 568 if (client != null)
430 { 569 {
431 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>(); 570 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
432 571
572 int baseCost = 0;
433 if (mm != null) 573 if (mm != null)
574 baseCost = mm.UploadCharge;
575
576 string warning = String.Empty;
577
578 if (llsdRequest.asset_type == "mesh")
434 { 579 {
435 if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) 580 string error;
581 int modelcost;
582
583
584 if (!m_ModelCost.MeshModelCost(llsdRequest.asset_resources, baseCost, out modelcost,
585 meshcostdata, out error, ref warning))
436 { 586 {
437 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); 587 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
588 resperror.message = error;
589 resperror.identifier = UUID.Zero;
438 590
439 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse(); 591 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
440 errorResponse.uploader = ""; 592 errorResponse.uploader = "";
441 errorResponse.state = "error"; 593 errorResponse.state = "error";
594 errorResponse.error = resperror;
595
596 lock (m_ModelCost)
597 m_FileAgentInventoryState = FileAgentInventoryState.idle;
442 return errorResponse; 598 return errorResponse;
443 } 599 }
600 cost = modelcost;
601 }
602 else
603 {
604 cost = baseCost;
605 }
606
607 if (cost > 0 && mm != null)
608 {
609 // check for test upload
610
611 if (m_ForceFreeTestUpload) // all are test
612 {
613 if (!(assetName.Length > 5 && assetName.StartsWith("TEST-"))) // has normal name lets change it
614 assetName = "TEST-" + assetName;
615
616 IsAtestUpload = true;
617 }
618
619 else if (m_enableFreeTestUpload) // only if prefixed with "TEST-"
620 {
621
622 IsAtestUpload = (assetName.Length > 5 && assetName.StartsWith("TEST-"));
623 }
624
625
626 if(IsAtestUpload) // let user know, still showing cost estimation
627 warning += "Upload will have no cost, for testing purposes only. Other uses are prohibited. Items will not work after 48 hours or on other regions";
628
629 // check funds
630 else
631 {
632 if (!mm.UploadCovered(client.AgentId, (int)cost))
633 {
634 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
635 resperror.message = "Insuficient funds";
636 resperror.identifier = UUID.Zero;
637
638 LLSDAssetUploadResponse errorResponse = new LLSDAssetUploadResponse();
639 errorResponse.uploader = "";
640 errorResponse.state = "error";
641 errorResponse.error = resperror;
642 lock (m_ModelCost)
643 m_FileAgentInventoryState = FileAgentInventoryState.idle;
644 return errorResponse;
645 }
646 }
444 } 647 }
648
649 if (client != null && warning != String.Empty)
650 client.SendAgentAlertMessage(warning, true);
445 } 651 }
446 } 652 }
447 653
448 string assetName = llsdRequest.name;
449 string assetDes = llsdRequest.description; 654 string assetDes = llsdRequest.description;
450 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath; 655 string capsBase = "/CAPS/" + m_HostCapsObj.CapsObjectPath;
451 UUID newAsset = UUID.Random(); 656 UUID newAsset = UUID.Random();
452 UUID newInvItem = UUID.Random(); 657 UUID newInvItem = UUID.Random();
453 UUID parentFolder = llsdRequest.folder_id; 658 UUID parentFolder = llsdRequest.folder_id;
454 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); 659 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000");
660 UUID texturesFolder = UUID.Zero;
661
662 if(!IsAtestUpload && m_enableModelUploadTextureToInventory)
663 texturesFolder = llsdRequest.texture_folder_id;
455 664
456 AssetUploader uploader = 665 AssetUploader uploader =
457 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type, 666 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
458 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile); 667 llsdRequest.asset_type, capsBase + uploaderPath, m_HostCapsObj.HttpListener, m_dumpAssetsToFile, cost,
668 texturesFolder, nreqtextures, nreqmeshs, nreqinstances, IsAtestUpload);
459 669
460 m_HostCapsObj.HttpListener.AddStreamHandler( 670 m_HostCapsObj.HttpListener.AddStreamHandler(
461 new BinaryStreamHandler( 671 new BinaryStreamHandler(
@@ -473,10 +683,22 @@ namespace OpenSim.Region.ClientStack.Linden
473 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase + 683 string uploaderURL = protocol + m_HostCapsObj.HostName + ":" + m_HostCapsObj.Port.ToString() + capsBase +
474 uploaderPath; 684 uploaderPath;
475 685
686
476 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse(); 687 LLSDAssetUploadResponse uploadResponse = new LLSDAssetUploadResponse();
477 uploadResponse.uploader = uploaderURL; 688 uploadResponse.uploader = uploaderURL;
478 uploadResponse.state = "upload"; 689 uploadResponse.state = "upload";
690 uploadResponse.upload_price = (int)cost;
691
692 if (llsdRequest.asset_type == "mesh")
693 {
694 uploadResponse.data = meshcostdata;
695 }
696
479 uploader.OnUpLoad += UploadCompleteHandler; 697 uploader.OnUpLoad += UploadCompleteHandler;
698
699 lock (m_ModelCost)
700 m_FileAgentInventoryState = FileAgentInventoryState.waitUpload;
701
480 return uploadResponse; 702 return uploadResponse;
481 } 703 }
482 704
@@ -488,8 +710,14 @@ namespace OpenSim.Region.ClientStack.Linden
488 /// <param name="data"></param> 710 /// <param name="data"></param>
489 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID, 711 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
490 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, 712 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
491 string assetType) 713 string assetType, int cost,
714 UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
715 bool IsAtestUpload, ref string error)
492 { 716 {
717
718 lock (m_ModelCost)
719 m_FileAgentInventoryState = FileAgentInventoryState.processUpload;
720
493 m_log.DebugFormat( 721 m_log.DebugFormat(
494 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}", 722 "[BUNCH OF CAPS]: Uploaded asset {0} for inventory item {1}, inv type {2}, asset type {3}",
495 assetID, inventoryItem, inventoryType, assetType); 723 assetID, inventoryItem, inventoryType, assetType);
@@ -497,6 +725,34 @@ namespace OpenSim.Region.ClientStack.Linden
497 sbyte assType = 0; 725 sbyte assType = 0;
498 sbyte inType = 0; 726 sbyte inType = 0;
499 727
728 IClientAPI client = null;
729
730 UUID owner_id = m_HostCapsObj.AgentID;
731 UUID creatorID;
732
733 bool istest = IsAtestUpload && m_enableFreeTestUpload && (cost > 0);
734
735 bool restrictPerms = m_RestrictFreeTestUploadPerms && istest;
736
737 if (istest && m_testAssetsCreatorID != UUID.Zero)
738 creatorID = m_testAssetsCreatorID;
739 else
740 creatorID = owner_id;
741
742 string creatorIDstr = creatorID.ToString();
743
744 IMoneyModule mm = m_Scene.RequestModuleInterface<IMoneyModule>();
745 if (mm != null)
746 {
747 // make sure client still has enougth credit
748 if (!mm.UploadCovered(m_HostCapsObj.AgentID, (int)cost))
749 {
750 error = "Insufficient funds.";
751 return;
752 }
753 }
754
755 // strings to types
500 if (inventoryType == "sound") 756 if (inventoryType == "sound")
501 { 757 {
502 inType = (sbyte)InventoryType.Sound; 758 inType = (sbyte)InventoryType.Sound;
@@ -511,6 +767,12 @@ namespace OpenSim.Region.ClientStack.Linden
511 inType = (sbyte)InventoryType.Animation; 767 inType = (sbyte)InventoryType.Animation;
512 assType = (sbyte)AssetType.Animation; 768 assType = (sbyte)AssetType.Animation;
513 } 769 }
770 else if (inventoryType == "animset")
771 {
772 inType = (sbyte)CustomInventoryType.AnimationSet;
773 assType = (sbyte)CustomAssetType.AnimationSet;
774 m_log.Debug("got animset upload request");
775 }
514 else if (inventoryType == "wearable") 776 else if (inventoryType == "wearable")
515 { 777 {
516 inType = (sbyte)InventoryType.Wearable; 778 inType = (sbyte)InventoryType.Wearable;
@@ -526,159 +788,253 @@ namespace OpenSim.Region.ClientStack.Linden
526 } 788 }
527 else if (inventoryType == "object") 789 else if (inventoryType == "object")
528 { 790 {
529 inType = (sbyte)InventoryType.Object; 791 if (assetType == "mesh") // this code for now is for mesh models uploads only
530 assType = (sbyte)AssetType.Object;
531
532 List<Vector3> positions = new List<Vector3>();
533 List<Quaternion> rotations = new List<Quaternion>();
534 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
535 OSDArray instance_list = (OSDArray)request["instance_list"];
536 OSDArray mesh_list = (OSDArray)request["mesh_list"];
537 OSDArray texture_list = (OSDArray)request["texture_list"];
538 SceneObjectGroup grp = null;
539
540 InventoryFolderBase textureUploadFolder = null;
541
542 List<InventoryFolderBase> foldersToUpdate = new List<InventoryFolderBase>();
543 List<InventoryItemBase> itemsToUpdate = new List<InventoryItemBase>();
544 IClientInventory clientInv = null;
545
546 if (texture_list.Count > 0)
547 { 792 {
548 ScenePresence avatar = null; 793 inType = (sbyte)InventoryType.Object;
549 m_Scene.TryGetScenePresence(m_HostCapsObj.AgentID, out avatar); 794 assType = (sbyte)AssetType.Object;
795
796 List<Vector3> positions = new List<Vector3>();
797 List<Quaternion> rotations = new List<Quaternion>();
798 OSDMap request = (OSDMap)OSDParser.DeserializeLLSDXml(data);
799
800 // compare and get updated information
801/* does nothing still we do need something to avoid special viewer to upload something diferent from the cost estimation
802 bool mismatchError = true;
550 803
551 if (avatar != null) 804 while (mismatchError)
552 { 805 {
553 IClientCore core = (IClientCore)avatar.ControllingClient; 806 mismatchError = false;
807 }
808
809 if (mismatchError)
810 {
811 error = "Upload and fee estimation information don't match";
812 lock (m_ModelCost)
813 m_FileAgentInventoryState = FileAgentInventoryState.idle;
814
815 return;
816 }
817*/
818 OSDArray instance_list = (OSDArray)request["instance_list"];
819 OSDArray mesh_list = (OSDArray)request["mesh_list"];
820 OSDArray texture_list = (OSDArray)request["texture_list"];
821 SceneObjectGroup grp = null;
822
823 // create and store texture assets
824 bool doTextInv = (!istest && m_enableModelUploadTextureToInventory &&
825 texturesFolder != UUID.Zero);
554 826
555 if (core.TryGet<IClientInventory>(out clientInv)) 827
828 List<UUID> textures = new List<UUID>();
829
830
831// if (doTextInv)
832 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
833
834 if(client == null) // don't put textures in inventory if there is no client
835 doTextInv = false;
836
837 for (int i = 0; i < texture_list.Count; i++)
838 {
839 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, creatorIDstr);
840 textureAsset.Data = texture_list[i].AsBinary();
841 if (istest)
842 textureAsset.Local = true;
843 m_assetService.Store(textureAsset);
844 textures.Add(textureAsset.FullID);
845
846 if (doTextInv)
556 { 847 {
557 var systemTextureFolder = m_Scene.InventoryService.GetFolderForType(m_HostCapsObj.AgentID, FolderType.Texture); 848 string name = assetName;
558 textureUploadFolder = new InventoryFolderBase(UUID.Random(), assetName, m_HostCapsObj.AgentID, (short)FolderType.None, systemTextureFolder.ID, 1); 849 if (name.Length > 25)
559 if (m_Scene.InventoryService.AddFolder(textureUploadFolder)) 850 name = name.Substring(0, 24);
560 { 851 name += "_Texture#" + i.ToString();
561 foldersToUpdate.Add(textureUploadFolder); 852 InventoryItemBase texitem = new InventoryItemBase();
853 texitem.Owner = m_HostCapsObj.AgentID;
854 texitem.CreatorId = creatorIDstr;
855 texitem.CreatorData = String.Empty;
856 texitem.ID = UUID.Random();
857 texitem.AssetID = textureAsset.FullID;
858 texitem.Description = "mesh model texture";
859 texitem.Name = name;
860 texitem.AssetType = (int)AssetType.Texture;
861 texitem.InvType = (int)InventoryType.Texture;
862 texitem.Folder = texturesFolder;
863
864 texitem.CurrentPermissions
865 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
866
867 texitem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
868 texitem.EveryOnePermissions = 0;
869 texitem.NextPermissions = (uint)PermissionMask.All;
870 texitem.CreationDate = Util.UnixTimeSinceEpoch();
871
872 m_Scene.AddInventoryItem(client, texitem);
873 texitem = null;
874 }
875 }
562 876
563 m_log.DebugFormat( 877 // create and store meshs assets
564 "[BUNCH OF CAPS]: Created new folder '{0}' ({1}) for textures uploaded with mesh object {2}", 878 List<UUID> meshAssets = new List<UUID>();
565 textureUploadFolder.Name, textureUploadFolder.ID, assetName); 879 List<bool> meshAvatarSkeletons = new List<bool>();
566 } 880 List<bool> meshAvatarColliders = new List<bool>();
567 else 881
882 bool curAvSkeleton;
883 bool curAvCollider;
884 for (int i = 0; i < mesh_list.Count; i++)
885 {
886 curAvSkeleton = false;
887 curAvCollider = false;
888
889 // we do need to parse the mesh now
890 OSD osd = OSDParser.DeserializeLLSDBinary(mesh_list[i]);
891 if (osd is OSDMap)
892 {
893 OSDMap mosd = (OSDMap)osd;
894 if (mosd.ContainsKey("skeleton"))
568 { 895 {
569 textureUploadFolder = null; 896 OSDMap skeleton = (OSDMap)mosd["skeleton"];
897 int sksize = skeleton["size"].AsInteger();
898 if (sksize > 0)
899 curAvSkeleton = true;
570 } 900 }
571 } 901 }
572 }
573 }
574 902
575 List<UUID> textures = new List<UUID>(); 903 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, creatorIDstr);
576 for (int i = 0; i < texture_list.Count; i++) 904 meshAsset.Data = mesh_list[i].AsBinary();
577 { 905 if (istest)
578 AssetBase textureAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Texture, ""); 906 meshAsset.Local = true;
579 textureAsset.Data = texture_list[i].AsBinary(); 907 m_assetService.Store(meshAsset);
580 m_assetService.Store(textureAsset); 908 meshAssets.Add(meshAsset.FullID);
581 textures.Add(textureAsset.FullID); 909 meshAvatarSkeletons.Add(curAvSkeleton);
910 meshAvatarColliders.Add(curAvCollider);
911
912 // test code
913 if (curAvSkeleton && client != null)
914 {
915 string name = assetName;
916 if (name.Length > 25)
917 name = name.Substring(0, 24);
918 name += "_Mesh#" + i.ToString();
919 InventoryItemBase meshitem = new InventoryItemBase();
920 meshitem.Owner = m_HostCapsObj.AgentID;
921 meshitem.CreatorId = creatorIDstr;
922 meshitem.CreatorData = String.Empty;
923 meshitem.ID = UUID.Random();
924 meshitem.AssetID = meshAsset.FullID;
925 meshitem.Description = "mesh ";
926 meshitem.Name = name;
927 meshitem.AssetType = (int)AssetType.Mesh;
928 meshitem.InvType = (int)InventoryType.Mesh;
929 // meshitem.Folder = UUID.Zero; // send to default
930
931 meshitem.Folder = parentFolder; // dont let it go to folder Meshes that viewers dont show
932
933 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
934 // (owner) permissions. This becomes a problem if next permissions are changed.
935 meshitem.CurrentPermissions
936 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
937
938 meshitem.BasePermissions = (uint)PermissionMask.All;
939 meshitem.EveryOnePermissions = 0;
940 meshitem.NextPermissions = (uint)PermissionMask.All;
941 meshitem.CreationDate = Util.UnixTimeSinceEpoch();
942
943 m_Scene.AddInventoryItem(client, meshitem);
944 meshitem = null;
945 }
946 }
582 947
583 if (textureUploadFolder != null) 948 int skipedMeshs = 0;
949 // build prims from instances
950 for (int i = 0; i < instance_list.Count; i++)
584 { 951 {
585 InventoryItemBase textureItem = new InventoryItemBase(); 952 OSDMap inner_instance_list = (OSDMap)instance_list[i];
586 textureItem.Owner = m_HostCapsObj.AgentID;
587 textureItem.CreatorId = m_HostCapsObj.AgentID.ToString();
588 textureItem.CreatorData = String.Empty;
589 textureItem.ID = UUID.Random();
590 textureItem.AssetID = textureAsset.FullID;
591 textureItem.Description = assetDescription;
592 textureItem.Name = assetName + " - Texture " + (i + 1).ToString();
593 textureItem.AssetType = (int)AssetType.Texture;
594 textureItem.InvType = (int)InventoryType.Texture;
595 textureItem.Folder = textureUploadFolder.ID;
596 textureItem.CurrentPermissions
597 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
598 textureItem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
599 textureItem.EveryOnePermissions = 0;
600 textureItem.NextPermissions = (uint)PermissionMask.All;
601 textureItem.CreationDate = Util.UnixTimeSinceEpoch();
602 m_Scene.InventoryService.AddItem(textureItem);
603 itemsToUpdate.Add(textureItem);
604
605 m_log.DebugFormat(
606 "[BUNCH OF CAPS]: Created new inventory item '{0}' ({1}) for texture uploaded with mesh object {2}",
607 textureItem.Name, textureItem.ID, assetName);
608 }
609 }
610 953
611 if (clientInv != null && (foldersToUpdate.Count > 0 || itemsToUpdate.Count > 0)) 954 // skip prims that are 2 small
612 { 955 Vector3 scale = inner_instance_list["scale"].AsVector3();
613 clientInv.SendBulkUpdateInventory(foldersToUpdate.ToArray(), itemsToUpdate.ToArray());
614 }
615 956
616 for (int i = 0; i < mesh_list.Count; i++) 957 if (scale.X < m_PrimScaleMin || scale.Y < m_PrimScaleMin || scale.Z < m_PrimScaleMin)
617 { 958 {
618 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 959 skipedMeshs++;
960 continue;
961 }
619 962
620 Primitive.TextureEntry textureEntry 963 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
621 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
622 OSDMap inner_instance_list = (OSDMap)instance_list[i];
623 964
624 OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; 965 Primitive.TextureEntry textureEntry
625 for (uint face = 0; face < face_list.Count; face++) 966 = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE);
626 {
627 OSDMap faceMap = (OSDMap)face_list[(int)face];
628 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
629 if(faceMap.ContainsKey("fullbright"))
630 f.Fullbright = faceMap["fullbright"].AsBoolean();
631 if (faceMap.ContainsKey ("diffuse_color"))
632 f.RGBA = faceMap["diffuse_color"].AsColor4();
633 967
634 int textureNum = faceMap["image"].AsInteger();
635 float imagerot = faceMap["imagerot"].AsInteger();
636 float offsets = (float)faceMap["offsets"].AsReal();
637 float offsett = (float)faceMap["offsett"].AsReal();
638 float scales = (float)faceMap["scales"].AsReal();
639 float scalet = (float)faceMap["scalet"].AsReal();
640 968
641 if(imagerot != 0) 969 OSDArray face_list = (OSDArray)inner_instance_list["face_list"];
642 f.Rotation = imagerot; 970 for (uint face = 0; face < face_list.Count; face++)
971 {
972 OSDMap faceMap = (OSDMap)face_list[(int)face];
973 Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face);
974 if (faceMap.ContainsKey("fullbright"))
975 f.Fullbright = faceMap["fullbright"].AsBoolean();
976 if (faceMap.ContainsKey("diffuse_color"))
977 f.RGBA = faceMap["diffuse_color"].AsColor4();
643 978
644 if(offsets != 0) 979 int textureNum = faceMap["image"].AsInteger();
645 f.OffsetU = offsets; 980 float imagerot = faceMap["imagerot"].AsInteger();
981 float offsets = (float)faceMap["offsets"].AsReal();
982 float offsett = (float)faceMap["offsett"].AsReal();
983 float scales = (float)faceMap["scales"].AsReal();
984 float scalet = (float)faceMap["scalet"].AsReal();
646 985
647 if (offsett != 0) 986 if (imagerot != 0)
648 f.OffsetV = offsett; 987 f.Rotation = imagerot;
649 988
650 if (scales != 0) 989 if (offsets != 0)
651 f.RepeatU = scales; 990 f.OffsetU = offsets;
652 991
653 if (scalet != 0) 992 if (offsett != 0)
654 f.RepeatV = scalet; 993 f.OffsetV = offsett;
655 994
656 if (textures.Count > textureNum) 995 if (scales != 0)
657 f.TextureID = textures[textureNum]; 996 f.RepeatU = scales;
658 else
659 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
660 997
661 textureEntry.FaceTextures[face] = f; 998 if (scalet != 0)
662 } 999 f.RepeatV = scalet;
663 1000
664 pbs.TextureEntry = textureEntry.GetBytes(); 1001 if (textures.Count > textureNum)
1002 f.TextureID = textures[textureNum];
1003 else
1004 f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE;
665 1005
666 AssetBase meshAsset = new AssetBase(UUID.Random(), assetName, (sbyte)AssetType.Mesh, ""); 1006 textureEntry.FaceTextures[face] = f;
667 meshAsset.Data = mesh_list[i].AsBinary(); 1007 }
668 m_assetService.Store(meshAsset);
669 1008
670 pbs.SculptEntry = true; 1009 pbs.TextureEntry = textureEntry.GetBytes();
671 pbs.SculptTexture = meshAsset.FullID;
672 pbs.SculptType = (byte)SculptType.Mesh;
673 pbs.SculptData = meshAsset.Data;
674 1010
675 Vector3 position = inner_instance_list["position"].AsVector3(); 1011 bool hasmesh = false;
676 Vector3 scale = inner_instance_list["scale"].AsVector3(); 1012 if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ...
677 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); 1013 {
1014 int meshindx = inner_instance_list["mesh"].AsInteger();
1015 if (meshAssets.Count > meshindx)
1016 {
1017 pbs.SculptEntry = true;
1018 pbs.SculptType = (byte)SculptType.Mesh;
1019 pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction
1020 // data will be requested from asset on rez (i hope)
1021 hasmesh = true;
1022 }
1023 }
1024
1025 Vector3 position = inner_instance_list["position"].AsVector3();
1026 Quaternion rotation = inner_instance_list["rotation"].AsQuaternion();
1027
1028 // for now viwers do send fixed defaults
1029 // but this may change
1030// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
1031 byte physicsShapeType = (byte)PhysShapeType.prim; // default for mesh is simple convex
1032 if(hasmesh)
1033 physicsShapeType = (byte) PhysShapeType.convex; // default for mesh is simple convex
1034// int material = inner_instance_list["material"].AsInteger();
1035 byte material = (byte)Material.Wood;
678 1036
679// no longer used - begin ------------------------ 1037// no longer used - begin ------------------------
680// int physicsShapeType = inner_instance_list["physics_shape_type"].AsInteger();
681// int material = inner_instance_list["material"].AsInteger();
682// int mesh = inner_instance_list["mesh"].AsInteger(); 1038// int mesh = inner_instance_list["mesh"].AsInteger();
683 1039
684// OSDMap permissions = (OSDMap)inner_instance_list["permissions"]; 1040// OSDMap permissions = (OSDMap)inner_instance_list["permissions"];
@@ -693,24 +1049,49 @@ namespace OpenSim.Region.ClientStack.Linden
693// UUID owner_id = permissions["owner_id"].AsUUID(); 1049// UUID owner_id = permissions["owner_id"].AsUUID();
694// int owner_mask = permissions["owner_mask"].AsInteger(); 1050// int owner_mask = permissions["owner_mask"].AsInteger();
695// no longer used - end ------------------------ 1051// no longer used - end ------------------------
1052
1053
1054 SceneObjectPart prim
1055 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero);
1056
1057 prim.Scale = scale;
1058 rotations.Add(rotation);
1059 positions.Add(position);
1060 prim.UUID = UUID.Random();
1061 prim.CreatorID = creatorID;
1062 prim.OwnerID = owner_id;
1063 prim.GroupID = UUID.Zero;
1064 prim.LastOwnerID = creatorID;
1065 prim.CreationDate = Util.UnixTimeSinceEpoch();
1066
1067 if (grp == null)
1068 prim.Name = assetName;
1069 else
1070 prim.Name = assetName + "#" + i.ToString();
696 1071
697 UUID owner_id = m_HostCapsObj.AgentID; 1072 prim.EveryoneMask = 0;
1073 prim.GroupMask = 0;
698 1074
699 SceneObjectPart prim 1075 if (restrictPerms)
700 = new SceneObjectPart(owner_id, pbs, position, Quaternion.Identity, Vector3.Zero); 1076 {
1077 prim.BaseMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
1078 prim.OwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify);
1079 prim.NextOwnerMask = 0;
1080 }
1081 else
1082 {
1083 prim.BaseMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1084 prim.OwnerMask = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1085 prim.NextOwnerMask = (uint)PermissionMask.Transfer;
1086 }
701 1087
702 prim.Scale = scale; 1088 if(istest)
703 //prim.OffsetPosition = position; 1089 prim.Description = "For testing only. Other uses are prohibited";
704 rotations.Add(rotation); 1090 else
705 positions.Add(position); 1091 prim.Description = "";
706 prim.UUID = UUID.Random(); 1092
707 prim.CreatorID = owner_id; 1093 prim.Material = material;
708 prim.OwnerID = owner_id; 1094 prim.PhysicsShapeType = physicsShapeType;
709 prim.GroupID = UUID.Zero;
710 prim.LastOwnerID = prim.OwnerID;
711 prim.CreationDate = Util.UnixTimeSinceEpoch();
712 prim.Name = assetName;
713 prim.Description = "";
714 1095
715// prim.BaseMask = (uint)base_mask; 1096// prim.BaseMask = (uint)base_mask;
716// prim.EveryoneMask = (uint)everyone_mask; 1097// prim.EveryoneMask = (uint)everyone_mask;
@@ -718,52 +1099,64 @@ namespace OpenSim.Region.ClientStack.Linden
718// prim.NextOwnerMask = (uint)next_owner_mask; 1099// prim.NextOwnerMask = (uint)next_owner_mask;
719// prim.OwnerMask = (uint)owner_mask; 1100// prim.OwnerMask = (uint)owner_mask;
720 1101
721 if (grp == null) 1102 if (grp == null)
722 grp = new SceneObjectGroup(prim); 1103 {
723 else 1104 grp = new SceneObjectGroup(prim);
724 grp.AddPart(prim); 1105 grp.LastOwnerID = creatorID;
725 } 1106 }
1107 else
1108 grp.AddPart(prim);
1109 }
726 1110
727 Vector3 rootPos = positions[0]; 1111 Vector3 rootPos = positions[0];
728 1112
729 if (grp.Parts.Length > 1) 1113 if (grp.Parts.Length > 1)
730 { 1114 {
731 // Fix first link number 1115 // Fix first link number
732 grp.RootPart.LinkNum++; 1116 grp.RootPart.LinkNum++;
733 1117
734 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]); 1118 Quaternion rootRotConj = Quaternion.Conjugate(rotations[0]);
735 Quaternion tmprot; 1119 Quaternion tmprot;
736 Vector3 offset; 1120 Vector3 offset;
737 1121
738 // fix children rotations and positions 1122 // fix children rotations and positions
739 for (int i = 1; i < rotations.Count; i++) 1123 for (int i = 1; i < rotations.Count; i++)
740 { 1124 {
741 tmprot = rotations[i]; 1125 tmprot = rotations[i];
742 tmprot = rootRotConj * tmprot; 1126 tmprot = rootRotConj * tmprot;
743 1127
744 grp.Parts[i].RotationOffset = tmprot; 1128 grp.Parts[i].RotationOffset = tmprot;
745 1129
746 offset = positions[i] - rootPos; 1130 offset = positions[i] - rootPos;
747 1131
748 offset *= rootRotConj; 1132 offset *= rootRotConj;
749 grp.Parts[i].OffsetPosition = offset; 1133 grp.Parts[i].OffsetPosition = offset;
1134 }
1135
1136 grp.AbsolutePosition = rootPos;
1137 grp.UpdateGroupRotationR(rotations[0]);
1138 }
1139 else
1140 {
1141 grp.AbsolutePosition = rootPos;
1142 grp.UpdateGroupRotationR(rotations[0]);
750 } 1143 }
751 1144
752 grp.AbsolutePosition = rootPos; 1145 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
753 grp.UpdateGroupRotationR(rotations[0]);
754 } 1146 }
755 else 1147
1148 else // not a mesh model
756 { 1149 {
757 grp.AbsolutePosition = rootPos; 1150 m_log.ErrorFormat("[CAPS Asset Upload] got unsuported assetType for object upload");
758 grp.UpdateGroupRotationR(rotations[0]); 1151 return;
759 } 1152 }
760
761 data = ASCIIEncoding.ASCII.GetBytes(SceneObjectSerializer.ToOriginalXmlFormat(grp));
762 } 1153 }
763 1154
764 AssetBase asset; 1155 AssetBase asset;
765 asset = new AssetBase(assetID, assetName, assType, m_HostCapsObj.AgentID.ToString()); 1156 asset = new AssetBase(assetID, assetName, assType, creatorIDstr);
766 asset.Data = data; 1157 asset.Data = data;
1158 if (istest)
1159 asset.Local = true;
767 if (AddNewAsset != null) 1160 if (AddNewAsset != null)
768 AddNewAsset(asset); 1161 AddNewAsset(asset);
769 else if (m_assetService != null) 1162 else if (m_assetService != null)
@@ -771,11 +1164,17 @@ namespace OpenSim.Region.ClientStack.Linden
771 1164
772 InventoryItemBase item = new InventoryItemBase(); 1165 InventoryItemBase item = new InventoryItemBase();
773 item.Owner = m_HostCapsObj.AgentID; 1166 item.Owner = m_HostCapsObj.AgentID;
774 item.CreatorId = m_HostCapsObj.AgentID.ToString(); 1167 item.CreatorId = creatorIDstr;
775 item.CreatorData = String.Empty; 1168 item.CreatorData = String.Empty;
776 item.ID = inventoryItem; 1169 item.ID = inventoryItem;
777 item.AssetID = asset.FullID; 1170 item.AssetID = asset.FullID;
778 item.Description = assetDescription; 1171 if (istest)
1172 {
1173 item.Description = "For testing only. Other uses are prohibited";
1174 item.Flags = (uint) (InventoryItemFlags.SharedSingleReference);
1175 }
1176 else
1177 item.Description = assetDescription;
779 item.Name = assetName; 1178 item.Name = assetName;
780 item.AssetType = assType; 1179 item.AssetType = assType;
781 item.InvType = inType; 1180 item.InvType = inType;
@@ -783,18 +1182,61 @@ namespace OpenSim.Region.ClientStack.Linden
783 1182
784 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current 1183 // If we set PermissionMask.All then when we rez the item the next permissions will replace the current
785 // (owner) permissions. This becomes a problem if next permissions are changed. 1184 // (owner) permissions. This becomes a problem if next permissions are changed.
786 item.CurrentPermissions
787 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Export);
788 1185
789 item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; 1186 if (inType == (sbyte)CustomInventoryType.AnimationSet)
790 item.EveryOnePermissions = 0; 1187 {
791 item.NextPermissions = (uint)PermissionMask.All; 1188 AnimationSet.setCreateItemPermitions(item);
1189 }
1190
1191 else if (restrictPerms)
1192 {
1193 item.BasePermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1194 item.CurrentPermissions = (uint)(PermissionMask.Move | PermissionMask.Modify);
1195 item.EveryOnePermissions = 0;
1196 item.NextPermissions = 0;
1197 }
1198 else
1199 {
1200 item.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1201 item.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1202 item.EveryOnePermissions = 0;
1203 item.NextPermissions = (uint)PermissionMask.Transfer;
1204 }
1205
792 item.CreationDate = Util.UnixTimeSinceEpoch(); 1206 item.CreationDate = Util.UnixTimeSinceEpoch();
793 1207
1208 m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client);
1209
794 if (AddNewInventoryItem != null) 1210 if (AddNewInventoryItem != null)
795 { 1211 {
796 AddNewInventoryItem(m_HostCapsObj.AgentID, item); 1212 if (istest)
1213 {
1214 m_Scene.AddInventoryItem(client, item);
1215/*
1216 AddNewInventoryItem(m_HostCapsObj.AgentID, item, 0);
1217 if (client != null)
1218 client.SendAgentAlertMessage("Upload will have no cost, for personal test purposes only. Other uses are forbiden. Items may not work on a another region" , true);
1219 */
1220 }
1221 else
1222 {
1223 AddNewInventoryItem(m_HostCapsObj.AgentID, item, (uint)cost);
1224// if (client != null)
1225// {
1226// // let users see anything.. i don't so far
1227// string str;
1228// if (cost > 0)
1229// // dont remember where is money unit name to put here
1230// str = "Upload complete. charged " + cost.ToString() + "$";
1231// else
1232// str = "Upload complete";
1233// client.SendAgentAlertMessage(str, true);
1234// }
1235 }
797 } 1236 }
1237
1238 lock (m_ModelCost)
1239 m_FileAgentInventoryState = FileAgentInventoryState.idle;
798 } 1240 }
799 1241
800 /// <summary> 1242 /// <summary>
@@ -935,24 +1377,17 @@ namespace OpenSim.Region.ClientStack.Linden
935 { 1377 {
936 string message; 1378 string message;
937 copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID, out message); 1379 copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID, out message);
938 if (client != null) 1380 if (copyItem != null && client != null)
939 { 1381 {
940 if (copyItem != null) 1382 m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder);
941 { 1383 client.SendBulkUpdateInventory(copyItem);
942 m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder);
943 client.SendBulkUpdateInventory(copyItem);
944 }
945 else
946 {
947 client.SendAgentAlertMessage(message, false);
948 }
949 } 1384 }
950 } 1385 }
951 else 1386 else
952 { 1387 {
953 m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID); 1388 m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID);
954 if (client != null) 1389 if (client != null)
955 client.SendAgentAlertMessage("Failed to retrieve item", false); 1390 client.SendAlertMessage("Failed to retrieve item");
956 } 1391 }
957 } 1392 }
958 catch (Exception e) 1393 catch (Exception e)
@@ -995,18 +1430,142 @@ namespace OpenSim.Region.ClientStack.Linden
995 return response; 1430 return response;
996 } 1431 }
997 1432
998 public string UpdateAgentInformation(string request, string path, 1433 public string GetObjectCost(string request, string path,
1434 string param, IOSHttpRequest httpRequest,
1435 IOSHttpResponse httpResponse)
1436 {
1437 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1438 OSDMap resp = new OSDMap();
1439
1440 OSDArray object_ids = (OSDArray)req["object_ids"];
1441
1442 for (int i = 0; i < object_ids.Count; i++)
1443 {
1444 UUID uuid = object_ids[i].AsUUID();
1445
1446 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1447
1448 if (part != null)
1449 {
1450 SceneObjectGroup grp = part.ParentGroup;
1451 if (grp != null)
1452 {
1453 float linksetCost;
1454 float linksetPhysCost;
1455 float partCost;
1456 float partPhysCost;
1457
1458 grp.GetResourcesCosts(part, out linksetCost, out linksetPhysCost, out partCost, out partPhysCost);
1459
1460 OSDMap object_data = new OSDMap();
1461 object_data["linked_set_resource_cost"] = linksetCost;
1462 object_data["resource_cost"] = partCost;
1463 object_data["physics_cost"] = partPhysCost;
1464 object_data["linked_set_physics_cost"] = linksetPhysCost;
1465
1466 resp[uuid.ToString()] = object_data;
1467 }
1468 else
1469 {
1470 OSDMap object_data = new OSDMap();
1471 object_data["linked_set_resource_cost"] = 0;
1472 object_data["resource_cost"] = 0;
1473 object_data["physics_cost"] = 0;
1474 object_data["linked_set_physics_cost"] = 0;
1475
1476 resp[uuid.ToString()] = object_data;
1477 }
1478
1479 }
1480 }
1481
1482 string response = OSDParser.SerializeLLSDXmlString(resp);
1483 return response;
1484 }
1485
1486 public string ResourceCostSelected(string request, string path,
999 string param, IOSHttpRequest httpRequest, 1487 string param, IOSHttpRequest httpRequest,
1000 IOSHttpResponse httpResponse) 1488 IOSHttpResponse httpResponse)
1001 { 1489 {
1002 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request); 1490 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1003 OSDMap accessPrefs = (OSDMap)req["access_prefs"]; 1491 OSDMap resp = new OSDMap();
1004 string desiredMaturity = accessPrefs["max"]; 1492
1493
1494 float phys=0;
1495 float stream=0;
1496 float simul=0;
1497
1498 if (req.ContainsKey("selected_roots"))
1499 {
1500 OSDArray object_ids = (OSDArray)req["selected_roots"];
1501
1502 // should go by SOG suming costs for all parts
1503 // ll v3 works ok with several objects select we get the list and adds ok
1504 // FS calls per object so results are wrong guess fs bug
1505 for (int i = 0; i < object_ids.Count; i++)
1506 {
1507 UUID uuid = object_ids[i].AsUUID();
1508 float Physc;
1509 float simulc;
1510 float streamc;
1511
1512 SceneObjectGroup grp = m_Scene.GetGroupByPrim(uuid);
1513 if (grp != null)
1514 {
1515 grp.GetSelectedCosts(out Physc, out streamc, out simulc);
1516 phys += Physc;
1517 stream += streamc;
1518 simul += simulc;
1519 }
1520 }
1521 }
1522 else if (req.ContainsKey("selected_prims"))
1523 {
1524 OSDArray object_ids = (OSDArray)req["selected_prims"];
1525
1526 // don't see in use in any of the 2 viewers
1527 // guess it should be for edit linked but... nothing
1528 // should go to SOP per part
1529 for (int i = 0; i < object_ids.Count; i++)
1530 {
1531 UUID uuid = object_ids[i].AsUUID();
1532
1533 SceneObjectPart part = m_Scene.GetSceneObjectPart(uuid);
1534 if (part != null)
1535 {
1536 phys += part.PhysicsCost;
1537 stream += part.StreamingCost;
1538 simul += part.SimulationCost;
1539 }
1540 }
1541 }
1542
1543 // if (simul != 0)
1544 {
1545 OSDMap object_data = new OSDMap();
1546
1547 object_data["physics"] = phys;
1548 object_data["streaming"] = stream;
1549 object_data["simulation"] = simul;
1550
1551 resp["selected"] = object_data;
1552 }
1553
1554 string response = OSDParser.SerializeLLSDXmlString(resp);
1555 return response;
1556 }
1005 1557
1558 public string UpdateAgentInformation(string request, string path,
1559 string param, IOSHttpRequest httpRequest,
1560 IOSHttpResponse httpResponse)
1561 {
1562// OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
1006 OSDMap resp = new OSDMap(); 1563 OSDMap resp = new OSDMap();
1007 OSDMap respAccessPrefs = new OSDMap(); 1564
1008 respAccessPrefs["max"] = desiredMaturity; // echoing the maturity back means success 1565 OSDMap accessPrefs = new OSDMap();
1009 resp["access_prefs"] = respAccessPrefs; 1566 accessPrefs["max"] = "A";
1567
1568 resp["access_prefs"] = accessPrefs;
1010 1569
1011 string response = OSDParser.SerializeLLSDXmlString(resp); 1570 string response = OSDParser.SerializeLLSDXmlString(resp);
1012 return response; 1571 return response;
@@ -1015,6 +1574,10 @@ namespace OpenSim.Region.ClientStack.Linden
1015 1574
1016 public class AssetUploader 1575 public class AssetUploader
1017 { 1576 {
1577 private static readonly ILog m_log =
1578 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
1579
1580
1018 public event UpLoadedAsset OnUpLoad; 1581 public event UpLoadedAsset OnUpLoad;
1019 private UpLoadedAsset handlerUpLoad = null; 1582 private UpLoadedAsset handlerUpLoad = null;
1020 1583
@@ -1029,10 +1592,21 @@ namespace OpenSim.Region.ClientStack.Linden
1029 1592
1030 private string m_invType = String.Empty; 1593 private string m_invType = String.Empty;
1031 private string m_assetType = String.Empty; 1594 private string m_assetType = String.Empty;
1032 1595 private int m_cost;
1596 private string m_error = String.Empty;
1597
1598 private Timer m_timeoutTimer = new Timer();
1599 private UUID m_texturesFolder;
1600 private int m_nreqtextures;
1601 private int m_nreqmeshs;
1602 private int m_nreqinstances;
1603 private bool m_IsAtestUpload;
1604
1033 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem, 1605 public AssetUploader(string assetName, string description, UUID assetID, UUID inventoryItem,
1034 UUID parentFolderID, string invType, string assetType, string path, 1606 UUID parentFolderID, string invType, string assetType, string path,
1035 IHttpServer httpServer, bool dumpAssetsToFile) 1607 IHttpServer httpServer, bool dumpAssetsToFile,
1608 int totalCost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
1609 bool IsAtestUpload)
1036 { 1610 {
1037 m_assetName = assetName; 1611 m_assetName = assetName;
1038 m_assetDes = description; 1612 m_assetDes = description;
@@ -1044,6 +1618,18 @@ namespace OpenSim.Region.ClientStack.Linden
1044 m_assetType = assetType; 1618 m_assetType = assetType;
1045 m_invType = invType; 1619 m_invType = invType;
1046 m_dumpAssetsToFile = dumpAssetsToFile; 1620 m_dumpAssetsToFile = dumpAssetsToFile;
1621 m_cost = totalCost;
1622
1623 m_texturesFolder = texturesFolder;
1624 m_nreqtextures = nreqtextures;
1625 m_nreqmeshs = nreqmeshs;
1626 m_nreqinstances = nreqinstances;
1627 m_IsAtestUpload = IsAtestUpload;
1628
1629 m_timeoutTimer.Elapsed += TimedOut;
1630 m_timeoutTimer.Interval = 120000;
1631 m_timeoutTimer.AutoReset = false;
1632 m_timeoutTimer.Start();
1047 } 1633 }
1048 1634
1049 /// <summary> 1635 /// <summary>
@@ -1058,12 +1644,14 @@ namespace OpenSim.Region.ClientStack.Linden
1058 UUID inv = inventoryItemID; 1644 UUID inv = inventoryItemID;
1059 string res = String.Empty; 1645 string res = String.Empty;
1060 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); 1646 LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete();
1647/*
1061 uploadComplete.new_asset = newAssetID.ToString(); 1648 uploadComplete.new_asset = newAssetID.ToString();
1062 uploadComplete.new_inventory_item = inv; 1649 uploadComplete.new_inventory_item = inv;
1063 uploadComplete.state = "complete"; 1650 uploadComplete.state = "complete";
1064 1651
1065 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); 1652 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1066 1653*/
1654 m_timeoutTimer.Stop();
1067 httpListener.RemoveStreamHandler("POST", uploaderPath); 1655 httpListener.RemoveStreamHandler("POST", uploaderPath);
1068 1656
1069 // TODO: probably make this a better set of extensions here 1657 // TODO: probably make this a better set of extensions here
@@ -1080,12 +1668,50 @@ namespace OpenSim.Region.ClientStack.Linden
1080 handlerUpLoad = OnUpLoad; 1668 handlerUpLoad = OnUpLoad;
1081 if (handlerUpLoad != null) 1669 if (handlerUpLoad != null)
1082 { 1670 {
1083 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType); 1671 handlerUpLoad(m_assetName, m_assetDes, newAssetID, inv, parentFolder, data, m_invType, m_assetType,
1672 m_cost, m_texturesFolder, m_nreqtextures, m_nreqmeshs, m_nreqinstances, m_IsAtestUpload,
1673 ref m_error);
1674 }
1675 if (m_IsAtestUpload)
1676 {
1677 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1678 resperror.message = "Upload SUCESSEFULL for testing purposes only. Other uses are prohibited. Item will not work after 48 hours or on other regions";
1679 resperror.identifier = inv;
1680
1681 uploadComplete.error = resperror;
1682 uploadComplete.state = "Upload4Testing";
1683 }
1684 else
1685 {
1686 if (m_error == String.Empty)
1687 {
1688 uploadComplete.new_asset = newAssetID.ToString();
1689 uploadComplete.new_inventory_item = inv;
1690 // if (m_texturesFolder != UUID.Zero)
1691 // uploadComplete.new_texture_folder_id = m_texturesFolder;
1692 uploadComplete.state = "complete";
1693 }
1694 else
1695 {
1696 LLSDAssetUploadError resperror = new LLSDAssetUploadError();
1697 resperror.message = m_error;
1698 resperror.identifier = inv;
1699
1700 uploadComplete.error = resperror;
1701 uploadComplete.state = "failed";
1702 }
1084 } 1703 }
1085 1704
1705 res = LLSDHelpers.SerialiseLLSDReply(uploadComplete);
1086 return res; 1706 return res;
1087 } 1707 }
1088 1708
1709 private void TimedOut(object sender, ElapsedEventArgs args)
1710 {
1711 m_log.InfoFormat("[CAPS]: Removing URL and handler for timed out mesh upload");
1712 httpListener.RemoveStreamHandler("POST", uploaderPath);
1713 }
1714
1089 ///Left this in and commented in case there are unforseen issues 1715 ///Left this in and commented in case there are unforseen issues
1090 //private void SaveAssetToFile(string filename, byte[] data) 1716 //private void SaveAssetToFile(string filename, byte[] data)
1091 //{ 1717 //{
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
new file mode 100644
index 0000000..f6a950f
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/MeshCost.cs
@@ -0,0 +1,727 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29using System;
30using System.IO;
31using System.Collections;
32using System.Collections.Generic;
33using System.Text;
34
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37
38using OpenSim.Framework;
39using OpenSim.Region.Framework;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Framework.Capabilities;
42
43using ComponentAce.Compression.Libs.zlib;
44
45using OSDArray = OpenMetaverse.StructuredData.OSDArray;
46using OSDMap = OpenMetaverse.StructuredData.OSDMap;
47
48namespace OpenSim.Region.ClientStack.Linden
49{
50 public struct ModelPrimLimits
51 {
52
53 }
54
55 public class ModelCost
56 {
57
58 // upload fee defaults
59 // fees are normalized to 1.0
60 // this parameters scale them to basic cost ( so 1.0 translates to 10 )
61
62 public float ModelMeshCostFactor = 0.0f; // scale total cost relative to basic (excluding textures)
63 public float ModelTextureCostFactor = 1.0f; // scale textures fee to basic.
64 public float ModelMinCostFactor = 0.0f; // 0.5f; // minimum total model free excluding textures
65
66 // itens costs in normalized values
67 // ie will be multiplied by basicCost and factors above
68 public float primCreationCost = 0.002f; // extra cost for each prim creation overhead
69 // weigthed size to normalized cost
70 public float bytecost = 1e-5f;
71
72 // mesh upload fees based on compressed data sizes
73 // several data sections are counted more that once
74 // to promote user optimization
75 // following parameters control how many extra times they are added
76 // to global size.
77 // LOD meshs
78 const float medSizeWth = 1f; // 2x
79 const float lowSizeWth = 1.5f; // 2.5x
80 const float lowestSizeWth = 2f; // 3x
81 // favor potencially physical optimized meshs versus automatic decomposition
82 const float physMeshSizeWth = 6f; // counts 7x
83 const float physHullSizeWth = 8f; // counts 9x
84
85 // stream cost area factors
86 // more or less like SL
87 const float highLodFactor = 17.36f;
88 const float midLodFactor = 277.78f;
89 const float lowLodFactor = 1111.11f;
90
91 // physics cost is below, identical to SL, assuming shape type convex
92 // server cost is below identical to SL assuming non scripted non physical object
93
94 // internal
95 const int bytesPerCoord = 6; // 3 coords, 2 bytes per each
96
97 // control prims dimensions
98 public float PrimScaleMin = 0.001f;
99 public float NonPhysicalPrimScaleMax = 256f;
100 public float PhysicalPrimScaleMax = 10f;
101 public int ObjectLinkedPartsMax = 512;
102
103 // storage for a single mesh asset cost parameters
104 private class ameshCostParam
105 {
106 // LOD sizes for size dependent streaming cost
107 public int highLODSize;
108 public int medLODSize;
109 public int lowLODSize;
110 public int lowestLODSize;
111 // normalized fee based on compressed data sizes
112 public float costFee;
113 // physics cost
114 public float physicsCost;
115 }
116
117 // calculates a mesh model costs
118 // returns false on error, with a reason on parameter error
119 // resources input LLSD request
120 // basicCost input region assets upload cost
121 // totalcost returns model total upload fee
122 // meshcostdata returns detailed costs for viewer
123 // avatarSkeleton if mesh includes a avatar skeleton
124 // useAvatarCollider if we should use physics mesh for avatar
125 public bool MeshModelCost(LLSDAssetResource resources, int basicCost, out int totalcost,
126 LLSDAssetUploadResponseData meshcostdata, out string error, ref string warning)
127 {
128 totalcost = 0;
129 error = string.Empty;
130
131 bool avatarSkeleton = false;
132
133 if (resources == null ||
134 resources.instance_list == null ||
135 resources.instance_list.Array.Count == 0)
136 {
137 error = "missing model information.";
138 return false;
139 }
140
141 int numberInstances = resources.instance_list.Array.Count;
142
143 if( numberInstances > ObjectLinkedPartsMax )
144 {
145 error = "Model whould have more than " + ObjectLinkedPartsMax.ToString() + " linked prims";
146 return false;
147 }
148
149 meshcostdata.model_streaming_cost = 0.0;
150 meshcostdata.simulation_cost = 0.0;
151 meshcostdata.physics_cost = 0.0;
152 meshcostdata.resource_cost = 0.0;
153
154 meshcostdata.upload_price_breakdown.mesh_instance = 0;
155 meshcostdata.upload_price_breakdown.mesh_physics = 0;
156 meshcostdata.upload_price_breakdown.mesh_streaming = 0;
157 meshcostdata.upload_price_breakdown.model = 0;
158
159 int itmp;
160
161 // textures cost
162 if (resources.texture_list != null && resources.texture_list.Array.Count > 0)
163 {
164 float textures_cost = (float)(resources.texture_list.Array.Count * basicCost);
165 textures_cost *= ModelTextureCostFactor;
166
167 itmp = (int)(textures_cost + 0.5f); // round
168 meshcostdata.upload_price_breakdown.texture = itmp;
169 totalcost += itmp;
170 }
171
172 // meshs assets cost
173 float meshsfee = 0;
174 int numberMeshs = 0;
175 bool haveMeshs = false;
176
177 bool curskeleton;
178 bool curAvatarPhys;
179
180 List<ameshCostParam> meshsCosts = new List<ameshCostParam>();
181
182 if (resources.mesh_list != null && resources.mesh_list.Array.Count > 0)
183 {
184 numberMeshs = resources.mesh_list.Array.Count;
185
186 for (int i = 0; i < numberMeshs; i++)
187 {
188 ameshCostParam curCost = new ameshCostParam();
189 byte[] data = (byte[])resources.mesh_list.Array[i];
190
191 if (!MeshCost(data, curCost,out curskeleton, out curAvatarPhys, out error))
192 {
193 return false;
194 }
195
196 if (curskeleton)
197 {
198 if (avatarSkeleton)
199 {
200 error = "model can only contain a avatar skeleton";
201 return false;
202 }
203 avatarSkeleton = true;
204 }
205 meshsCosts.Add(curCost);
206 meshsfee += curCost.costFee;
207 }
208 haveMeshs = true;
209 }
210
211 // instances (prims) cost
212
213
214 int mesh;
215 int skipedSmall = 0;
216 for (int i = 0; i < numberInstances; i++)
217 {
218 Hashtable inst = (Hashtable)resources.instance_list.Array[i];
219
220 ArrayList ascale = (ArrayList)inst["scale"];
221 Vector3 scale;
222 double tmp;
223 tmp = (double)ascale[0];
224 scale.X = (float)tmp;
225 tmp = (double)ascale[1];
226 scale.Y = (float)tmp;
227 tmp = (double)ascale[2];
228 scale.Z = (float)tmp;
229
230 if (scale.X < PrimScaleMin || scale.Y < PrimScaleMin || scale.Z < PrimScaleMin)
231 {
232 skipedSmall++;
233 continue;
234 }
235
236 if (scale.X > NonPhysicalPrimScaleMax || scale.Y > NonPhysicalPrimScaleMax || scale.Z > NonPhysicalPrimScaleMax)
237 {
238 error = "Model contains parts with sides larger than " + NonPhysicalPrimScaleMax.ToString() + "m. Please ajust scale";
239 return false;
240 }
241
242 if (haveMeshs && inst.ContainsKey("mesh"))
243 {
244 mesh = (int)inst["mesh"];
245
246 if (mesh >= numberMeshs)
247 {
248 error = "Incoerent model information.";
249 return false;
250 }
251
252 // streamming cost
253
254 float sqdiam = scale.LengthSquared();
255
256 ameshCostParam curCost = meshsCosts[mesh];
257 float mesh_streaming = streamingCost(curCost, sqdiam);
258
259 meshcostdata.model_streaming_cost += mesh_streaming;
260 meshcostdata.physics_cost += curCost.physicsCost;
261 }
262 else // instance as no mesh ??
263 {
264 // to do later if needed
265 meshcostdata.model_streaming_cost += 0.5f;
266 meshcostdata.physics_cost += 1.0f;
267 }
268
269 // assume unscripted and static prim server cost
270 meshcostdata.simulation_cost += 0.5f;
271 // charge for prims creation
272 meshsfee += primCreationCost;
273 }
274
275 if (skipedSmall > 0)
276 {
277 if (skipedSmall > numberInstances / 2)
278 {
279 error = "Model contains too many prims smaller than " + PrimScaleMin.ToString() +
280 "m minimum allowed size. Please check scalling";
281 return false;
282 }
283 else
284 warning += skipedSmall.ToString() + " of the requested " +numberInstances.ToString() +
285 " model prims will not upload because they are smaller than " + PrimScaleMin.ToString() +
286 "m minimum allowed size. Please check scalling ";
287 }
288
289 if (meshcostdata.physics_cost <= meshcostdata.model_streaming_cost)
290 meshcostdata.resource_cost = meshcostdata.model_streaming_cost;
291 else
292 meshcostdata.resource_cost = meshcostdata.physics_cost;
293
294 if (meshcostdata.resource_cost < meshcostdata.simulation_cost)
295 meshcostdata.resource_cost = meshcostdata.simulation_cost;
296
297 // scale cost
298 // at this point a cost of 1.0 whould mean basic cost
299 meshsfee *= ModelMeshCostFactor;
300
301 if (meshsfee < ModelMinCostFactor)
302 meshsfee = ModelMinCostFactor;
303
304 // actually scale it to basic cost
305 meshsfee *= (float)basicCost;
306
307 meshsfee += 0.5f; // rounding
308
309 totalcost += (int)meshsfee;
310
311 // breakdown prices
312 // don't seem to be in use so removed code for now
313
314 return true;
315 }
316
317 // single mesh asset cost
318 private bool MeshCost(byte[] data, ameshCostParam cost,out bool skeleton, out bool avatarPhys, out string error)
319 {
320 cost.highLODSize = 0;
321 cost.medLODSize = 0;
322 cost.lowLODSize = 0;
323 cost.lowestLODSize = 0;
324 cost.physicsCost = 0.0f;
325 cost.costFee = 0.0f;
326
327 error = string.Empty;
328
329 skeleton = false;
330 avatarPhys = false;
331
332 if (data == null || data.Length == 0)
333 {
334 error = "Missing model information.";
335 return false;
336 }
337
338 OSD meshOsd = null;
339 int start = 0;
340
341 error = "Invalid model data";
342
343 using (MemoryStream ms = new MemoryStream(data))
344 {
345 try
346 {
347 OSD osd = OSDParser.DeserializeLLSDBinary(ms);
348 if (osd is OSDMap)
349 meshOsd = (OSDMap)osd;
350 else
351 return false;
352 }
353 catch (Exception e)
354 {
355 return false;
356 }
357 start = (int)ms.Position;
358 }
359
360 OSDMap map = (OSDMap)meshOsd;
361 OSDMap tmpmap;
362
363 int highlod_size = 0;
364 int medlod_size = 0;
365 int lowlod_size = 0;
366 int lowestlod_size = 0;
367 int skin_size = 0;
368
369 int hulls_size = 0;
370 int phys_nhulls;
371 int phys_hullsvertices = 0;
372
373 int physmesh_size = 0;
374 int phys_ntriangles = 0;
375
376 int submesh_offset = -1;
377
378 if (map.ContainsKey("skeleton"))
379 {
380 tmpmap = (OSDMap)map["skeleton"];
381 if (tmpmap.ContainsKey("offset") && tmpmap.ContainsKey("size"))
382 {
383 int sksize = tmpmap["size"].AsInteger();
384 if(sksize > 0)
385 skeleton = true;
386 }
387 }
388
389 if (map.ContainsKey("physics_convex"))
390 {
391 tmpmap = (OSDMap)map["physics_convex"];
392 if (tmpmap.ContainsKey("offset"))
393 submesh_offset = tmpmap["offset"].AsInteger() + start;
394 if (tmpmap.ContainsKey("size"))
395 hulls_size = tmpmap["size"].AsInteger();
396 }
397
398 if (submesh_offset < 0 || hulls_size == 0)
399 {
400 error = "Missing physics_convex block";
401 return false;
402 }
403
404 if (!hulls(data, submesh_offset, hulls_size, out phys_hullsvertices, out phys_nhulls))
405 {
406 error = "Bad physics_convex block";
407 return false;
408 }
409
410 submesh_offset = -1;
411
412 // only look for LOD meshs sizes
413
414 if (map.ContainsKey("high_lod"))
415 {
416 tmpmap = (OSDMap)map["high_lod"];
417 // see at least if there is a offset for this one
418 if (tmpmap.ContainsKey("offset"))
419 submesh_offset = tmpmap["offset"].AsInteger() + start;
420 if (tmpmap.ContainsKey("size"))
421 highlod_size = tmpmap["size"].AsInteger();
422 }
423
424 if (submesh_offset < 0 || highlod_size <= 0)
425 {
426 error = "Missing high_lod block";
427 return false;
428 }
429
430 bool haveprev = true;
431
432 if (map.ContainsKey("medium_lod"))
433 {
434 tmpmap = (OSDMap)map["medium_lod"];
435 if (tmpmap.ContainsKey("size"))
436 medlod_size = tmpmap["size"].AsInteger();
437 else
438 haveprev = false;
439 }
440
441 if (haveprev && map.ContainsKey("low_lod"))
442 {
443 tmpmap = (OSDMap)map["low_lod"];
444 if (tmpmap.ContainsKey("size"))
445 lowlod_size = tmpmap["size"].AsInteger();
446 else
447 haveprev = false;
448 }
449
450 if (haveprev && map.ContainsKey("lowest_lod"))
451 {
452 tmpmap = (OSDMap)map["lowest_lod"];
453 if (tmpmap.ContainsKey("size"))
454 lowestlod_size = tmpmap["size"].AsInteger();
455 }
456
457 if (map.ContainsKey("skin"))
458 {
459 tmpmap = (OSDMap)map["skin"];
460 if (tmpmap.ContainsKey("size"))
461 skin_size = tmpmap["size"].AsInteger();
462 }
463
464 cost.highLODSize = highlod_size;
465 cost.medLODSize = medlod_size;
466 cost.lowLODSize = lowlod_size;
467 cost.lowestLODSize = lowestlod_size;
468
469 submesh_offset = -1;
470
471 tmpmap = null;
472 if(map.ContainsKey("physics_mesh"))
473 tmpmap = (OSDMap)map["physics_mesh"];
474 else if (map.ContainsKey("physics_shape")) // old naming
475 tmpmap = (OSDMap)map["physics_shape"];
476
477 if(tmpmap != null)
478 {
479 if (tmpmap.ContainsKey("offset"))
480 submesh_offset = tmpmap["offset"].AsInteger() + start;
481 if (tmpmap.ContainsKey("size"))
482 physmesh_size = tmpmap["size"].AsInteger();
483
484 if (submesh_offset >= 0 || physmesh_size > 0)
485 {
486
487 if (!submesh(data, submesh_offset, physmesh_size, out phys_ntriangles))
488 {
489 error = "Model data parsing error";
490 return false;
491 }
492 }
493 }
494
495 // upload is done in convex shape type so only one hull
496 phys_hullsvertices++;
497 cost.physicsCost = 0.04f * phys_hullsvertices;
498
499 float sfee;
500
501 sfee = data.Length; // start with total compressed data size
502
503 // penalize lod meshs that should be more builder optimized
504 sfee += medSizeWth * medlod_size;
505 sfee += lowSizeWth * lowlod_size;
506 sfee += lowestSizeWth * lowlod_size;
507
508 // physics
509 // favor potencial optimized meshs versus automatic decomposition
510 if (physmesh_size != 0)
511 sfee += physMeshSizeWth * (physmesh_size + hulls_size / 4); // reduce cost of mandatory convex hull
512 else
513 sfee += physHullSizeWth * hulls_size;
514
515 // bytes to money
516 sfee *= bytecost;
517
518 cost.costFee = sfee;
519 return true;
520 }
521
522 // parses a LOD or physics mesh component
523 private bool submesh(byte[] data, int offset, int size, out int ntriangles)
524 {
525 ntriangles = 0;
526
527 OSD decodedMeshOsd = new OSD();
528 byte[] meshBytes = new byte[size];
529 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
530 try
531 {
532 using (MemoryStream inMs = new MemoryStream(meshBytes))
533 {
534 using (MemoryStream outMs = new MemoryStream())
535 {
536 using (ZOutputStream zOut = new ZOutputStream(outMs))
537 {
538 byte[] readBuffer = new byte[4096];
539 int readLen = 0;
540 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
541 {
542 zOut.Write(readBuffer, 0, readLen);
543 }
544 zOut.Flush();
545 outMs.Seek(0, SeekOrigin.Begin);
546
547 byte[] decompressedBuf = outMs.GetBuffer();
548 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
549 }
550 }
551 }
552 }
553 catch (Exception e)
554 {
555 return false;
556 }
557
558 OSDArray decodedMeshOsdArray = null;
559 if ((!decodedMeshOsd is OSDArray))
560 return false;
561
562 byte[] dummy;
563
564 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
565 foreach (OSD subMeshOsd in decodedMeshOsdArray)
566 {
567 if (subMeshOsd is OSDMap)
568 {
569 OSDMap subtmpmap = (OSDMap)subMeshOsd;
570 if (subtmpmap.ContainsKey("NoGeometry") && ((OSDBoolean)subtmpmap["NoGeometry"]))
571 continue;
572
573 if (!subtmpmap.ContainsKey("Position"))
574 return false;
575
576 if (subtmpmap.ContainsKey("TriangleList"))
577 {
578 dummy = subtmpmap["TriangleList"].AsBinary();
579 ntriangles += dummy.Length / bytesPerCoord;
580 }
581 else
582 return false;
583 }
584 }
585
586 return true;
587 }
588
589 // parses convex hulls component
590 private bool hulls(byte[] data, int offset, int size, out int nvertices, out int nhulls)
591 {
592 nvertices = 0;
593 nhulls = 1;
594
595 OSD decodedMeshOsd = new OSD();
596 byte[] meshBytes = new byte[size];
597 System.Buffer.BlockCopy(data, offset, meshBytes, 0, size);
598 try
599 {
600 using (MemoryStream inMs = new MemoryStream(meshBytes))
601 {
602 using (MemoryStream outMs = new MemoryStream())
603 {
604 using (ZOutputStream zOut = new ZOutputStream(outMs))
605 {
606 byte[] readBuffer = new byte[4096];
607 int readLen = 0;
608 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
609 {
610 zOut.Write(readBuffer, 0, readLen);
611 }
612 zOut.Flush();
613 outMs.Seek(0, SeekOrigin.Begin);
614
615 byte[] decompressedBuf = outMs.GetBuffer();
616 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
617 }
618 }
619 }
620 }
621 catch (Exception e)
622 {
623 return false;
624 }
625
626 OSDMap cmap = (OSDMap)decodedMeshOsd;
627 if (cmap == null)
628 return false;
629
630 byte[] dummy;
631
632 // must have one of this
633 if (cmap.ContainsKey("BoundingVerts"))
634 {
635 dummy = cmap["BoundingVerts"].AsBinary();
636 nvertices = dummy.Length / bytesPerCoord;
637 }
638 else
639 return false;
640
641/* upload is done with convex shape type
642 if (cmap.ContainsKey("HullList"))
643 {
644 dummy = cmap["HullList"].AsBinary();
645 nhulls += dummy.Length;
646 }
647
648
649 if (cmap.ContainsKey("Positions"))
650 {
651 dummy = cmap["Positions"].AsBinary();
652 nvertices = dummy.Length / bytesPerCoord;
653 }
654 */
655
656 return true;
657 }
658
659 // returns streaming cost from on mesh LODs sizes in curCost and square of prim size length
660 private float streamingCost(ameshCostParam curCost, float sqdiam)
661 {
662 // compute efective areas
663 float ma = 262144f;
664
665 float mh = sqdiam * highLodFactor;
666 if (mh > ma)
667 mh = ma;
668 float mm = sqdiam * midLodFactor;
669 if (mm > ma)
670 mm = ma;
671
672 float ml = sqdiam * lowLodFactor;
673 if (ml > ma)
674 ml = ma;
675
676 float mlst = ma;
677
678 mlst -= ml;
679 ml -= mm;
680 mm -= mh;
681
682 if (mlst < 1.0f)
683 mlst = 1.0f;
684 if (ml < 1.0f)
685 ml = 1.0f;
686 if (mm < 1.0f)
687 mm = 1.0f;
688 if (mh < 1.0f)
689 mh = 1.0f;
690
691 ma = mlst + ml + mm + mh;
692
693 // get LODs compressed sizes
694 // giving 384 bytes bonus
695 int lst = curCost.lowestLODSize - 384;
696 int l = curCost.lowLODSize - 384;
697 int m = curCost.medLODSize - 384;
698 int h = curCost.highLODSize - 384;
699
700 // use previus higher LOD size on missing ones
701 if (m <= 0)
702 m = h;
703 if (l <= 0)
704 l = m;
705 if (lst <= 0)
706 lst = l;
707
708 // force minumum sizes
709 if (lst < 16)
710 lst = 16;
711 if (l < 16)
712 l = 16;
713 if (m < 16)
714 m = 16;
715 if (h < 16)
716 h = 16;
717
718 // compute cost weighted by relative effective areas
719 float cost = (float)lst * mlst + (float)l * ml + (float)m * mm + (float)h * mh;
720 cost /= ma;
721
722 cost *= 0.004f; // overall tunning parameter
723
724 return cost;
725 }
726 }
727}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 9b9f6a7..feb3322 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -78,7 +78,6 @@ namespace OpenSim.Region.ClientStack.Linden
78 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); 78 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
79 79
80 private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>(); 80 private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>();
81 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
82 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>(); 81 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
83 82
84 #region INonSharedRegionModule methods 83 #region INonSharedRegionModule methods
@@ -201,6 +200,7 @@ namespace OpenSim.Region.ClientStack.Linden
201 } 200 }
202 201
203 /// <summary> 202 /// <summary>
203
204 /// May return a null queue 204 /// May return a null queue
205 /// </summary> 205 /// </summary>
206 /// <param name="agentId"></param> 206 /// <param name="agentId"></param>
@@ -231,18 +231,12 @@ namespace OpenSim.Region.ClientStack.Linden
231 lock (queue) 231 lock (queue)
232 queue.Enqueue(ev); 232 queue.Enqueue(ev);
233 } 233 }
234 else if (DebugLevel > 0) 234 else
235 { 235 {
236 ScenePresence sp = m_scene.GetScenePresence(avatarID);
237
238 // This assumes that an NPC should never have a queue.
239 if (sp != null && sp.PresenceType != PresenceType.Npc)
240 {
241 OSDMap evMap = (OSDMap)ev; 236 OSDMap evMap = (OSDMap)ev;
242 m_log.WarnFormat( 237 m_log.WarnFormat(
243 "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} {1} when placing message {2} in region {3}", 238 "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} when placing message {1} in region {2}",
244 sp.Name, sp.UUID, evMap["message"], m_scene.Name); 239 avatarID, evMap["message"], m_scene.Name);
245 }
246 } 240 }
247 } 241 }
248 catch (NullReferenceException e) 242 catch (NullReferenceException e)
@@ -263,28 +257,13 @@ namespace OpenSim.Region.ClientStack.Linden
263 lock (queues) 257 lock (queues)
264 queues.Remove(agentID); 258 queues.Remove(agentID);
265 259
266 List<UUID> removeitems = new List<UUID>();
267 lock (m_AvatarQueueUUIDMapping) 260 lock (m_AvatarQueueUUIDMapping)
268 m_AvatarQueueUUIDMapping.Remove(agentID); 261 m_AvatarQueueUUIDMapping.Remove(agentID);
269 262
270 UUID searchval = UUID.Zero; 263 lock (m_ids)
271
272 removeitems.Clear();
273
274 lock (m_QueueUUIDAvatarMapping)
275 { 264 {
276 foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys) 265 if (!m_ids.ContainsKey(agentID))
277 { 266 m_ids.Remove(agentID);
278 searchval = m_QueueUUIDAvatarMapping[ky];
279
280 if (searchval == agentID)
281 {
282 removeitems.Add(ky);
283 }
284 }
285
286 foreach (UUID ky in removeitems)
287 m_QueueUUIDAvatarMapping.Remove(ky);
288 } 267 }
289 268
290 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 269 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
@@ -309,55 +288,95 @@ namespace OpenSim.Region.ClientStack.Linden
309 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", 288 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
310 agentID, caps, m_scene.RegionInfo.RegionName); 289 agentID, caps, m_scene.RegionInfo.RegionName);
311 290
312 // Let's instantiate a Queue for this agent right now
313 TryGetQueue(agentID);
314
315 UUID eventQueueGetUUID; 291 UUID eventQueueGetUUID;
292 Queue<OSD> queue;
293 Random rnd = new Random(Environment.TickCount);
294 int nrnd = rnd.Next(30000000);
295 if (nrnd < 0)
296 nrnd = -nrnd;
316 297
317 lock (m_AvatarQueueUUIDMapping) 298 lock (queues)
318 { 299 {
319 // Reuse open queues. The client does! 300 if (queues.ContainsKey(agentID))
320 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) 301 queue = queues[agentID];
302 else
303 queue = null;
304
305 if (queue == null)
321 { 306 {
322 //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); 307 queue = new Queue<OSD>();
323 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; 308 queues[agentID] = queue;
309
310 // push markers to handle old responses still waiting
311 // this will cost at most viewer getting two forced noevents
312 // even being a new queue better be safe
313 queue.Enqueue(null);
314 queue.Enqueue(null); // one should be enough
315
316 lock (m_AvatarQueueUUIDMapping)
317 {
318 eventQueueGetUUID = UUID.Random();
319 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
320 {
321 // oops this should not happen ?
322 m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID without a queue");
323 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
324 }
325 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
326 }
327 lock (m_ids)
328 {
329 if (!m_ids.ContainsKey(agentID))
330 m_ids.Add(agentID, nrnd);
331 else
332 m_ids[agentID] = nrnd;
333 }
324 } 334 }
325 else 335 else
326 { 336 {
327 eventQueueGetUUID = UUID.Random(); 337 // push markers to handle old responses still waiting
328 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); 338 // this will cost at most viewer getting two forced noevents
339 // even being a new queue better be safe
340 queue.Enqueue(null);
341 queue.Enqueue(null); // one should be enough
342
343 // reuse or not to reuse TODO FIX
344 lock (m_AvatarQueueUUIDMapping)
345 {
346 // Reuse open queues. The client does!
347 // Its reuse caps path not queues those are been reused already
348 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
349 {
350 m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
351 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
352 }
353 else
354 {
355 eventQueueGetUUID = UUID.Random();
356 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
357 m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
358 }
359 }
360 lock (m_ids)
361 {
362 // change to negative numbers so they are changed at end of sending first marker
363 // old data on a queue may be sent on a response for a new caps
364 // but at least will be sent with coerent IDs
365 if (!m_ids.ContainsKey(agentID))
366 m_ids.Add(agentID, -nrnd); // should not happen
367 else
368 m_ids[agentID] = -m_ids[agentID];
369 }
329 } 370 }
330 } 371 }
331 372
332 lock (m_QueueUUIDAvatarMapping)
333 {
334 if (!m_QueueUUIDAvatarMapping.ContainsKey(eventQueueGetUUID))
335 m_QueueUUIDAvatarMapping.Add(eventQueueGetUUID, agentID);
336 }
337
338 lock (m_AvatarQueueUUIDMapping)
339 {
340 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
341 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
342 }
343
344 caps.RegisterPollHandler( 373 caps.RegisterPollHandler(
345 "EventQueueGet", 374 "EventQueueGet",
346 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); 375 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
347
348 Random rnd = new Random(Environment.TickCount);
349 lock (m_ids)
350 {
351 if (!m_ids.ContainsKey(agentID))
352 m_ids.Add(agentID, rnd.Next(30000000));
353 }
354 } 376 }
355 377
356 public bool HasEvents(UUID requestID, UUID agentID) 378 public bool HasEvents(UUID requestID, UUID agentID)
357 { 379 {
358 // Don't use this, because of race conditions at agent closing time
359 //Queue<OSD> queue = TryGetQueue(agentID);
360
361 Queue<OSD> queue = GetQueue(agentID); 380 Queue<OSD> queue = GetQueue(agentID);
362 if (queue != null) 381 if (queue != null)
363 lock (queue) 382 lock (queue)
@@ -366,7 +385,8 @@ namespace OpenSim.Region.ClientStack.Linden
366 return queue.Count > 0; 385 return queue.Count > 0;
367 } 386 }
368 387
369 return false; 388 //m_log.WarnFormat("POLLED FOR EVENTS BY {0} unknown agent", agentID);
389 return true;
370 } 390 }
371 391
372 /// <summary> 392 /// <summary>
@@ -395,55 +415,65 @@ namespace OpenSim.Region.ClientStack.Linden
395 return NoEvents(requestID, pAgentId); 415 return NoEvents(requestID, pAgentId);
396 } 416 }
397 417
398 OSD element; 418 OSD element = null;;
419 OSDArray array = new OSDArray();
420 int thisID = 0;
421 bool negativeID = false;
422
399 lock (queue) 423 lock (queue)
400 { 424 {
401 if (queue.Count == 0) 425 if (queue.Count == 0)
402 return NoEvents(requestID, pAgentId); 426 return NoEvents(requestID, pAgentId);
403 element = queue.Dequeue(); // 15s timeout
404 }
405 427
406 int thisID = 0; 428 lock (m_ids)
407 lock (m_ids) 429 thisID = m_ids[pAgentId];
408 thisID = m_ids[pAgentId];
409 430
410 OSDArray array = new OSDArray(); 431 if (thisID < 0)
411 if (element == null) // didn't have an event in 15s
412 {
413 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
414 array.Add(EventQueueHelper.KeepAliveEvent());
415 //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName);
416 }
417 else
418 {
419 if (DebugLevel > 0)
420 LogOutboundDebugMessage(element, pAgentId);
421
422 array.Add(element);
423
424 lock (queue)
425 { 432 {
426 while (queue.Count > 0) 433 negativeID = true;
427 { 434 thisID = -thisID;
428 element = queue.Dequeue(); 435 }
436
437 while (queue.Count > 0)
438 {
439 element = queue.Dequeue();
440 // add elements until a marker is found
441 // so they get into a response
442 if (element == null)
443 break;
444 if (DebugLevel > 0)
445 LogOutboundDebugMessage(element, pAgentId);
446 array.Add(element);
447 thisID++;
448 }
449 }
429 450
430 if (DebugLevel > 0) 451 OSDMap events = null;
431 LogOutboundDebugMessage(element, pAgentId);
432 452
433 array.Add(element); 453 if (array.Count > 0)
434 thisID++; 454 {
435 } 455 events = new OSDMap();
436 } 456 events.Add("events", array);
457 events.Add("id", new OSDInteger(thisID));
437 } 458 }
438 459
439 OSDMap events = new OSDMap(); 460 if (negativeID && element == null)
440 events.Add("events", array); 461 {
462 Random rnd = new Random(Environment.TickCount);
463 thisID = rnd.Next(30000000);
464 if (thisID < 0)
465 thisID = -thisID;
466 }
441 467
442 events.Add("id", new OSDInteger(thisID));
443 lock (m_ids) 468 lock (m_ids)
444 { 469 {
445 m_ids[pAgentId] = thisID + 1; 470 m_ids[pAgentId] = thisID + 1;
446 } 471 }
472
473 // if there where no elements before a marker send a NoEvents
474 if (array.Count == 0)
475 return NoEvents(requestID, pAgentId);
476
447 Hashtable responsedata = new Hashtable(); 477 Hashtable responsedata = new Hashtable();
448 responsedata["int_response_code"] = 200; 478 responsedata["int_response_code"] = 200;
449 responsedata["content_type"] = "application/xml"; 479 responsedata["content_type"] = "application/xml";
@@ -461,260 +491,12 @@ namespace OpenSim.Region.ClientStack.Linden
461 responsedata["content_type"] = "text/plain"; 491 responsedata["content_type"] = "text/plain";
462 responsedata["keepalive"] = false; 492 responsedata["keepalive"] = false;
463 responsedata["reusecontext"] = false; 493 responsedata["reusecontext"] = false;
464 responsedata["str_response_string"] = "Upstream error: "; 494 responsedata["str_response_string"] = "<llsd></llsd>";
465 responsedata["error_status_text"] = "Upstream error:"; 495 responsedata["error_status_text"] = "<llsd></llsd>";
466 responsedata["http_protocol_version"] = "HTTP/1.0"; 496 responsedata["http_protocol_version"] = "HTTP/1.0";
467 return responsedata; 497 return responsedata;
468 } 498 }
469 499
470// public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
471// {
472// // TODO: this has to be redone to not busy-wait (and block the thread),
473// // TODO: as soon as we have a non-blocking way to handle HTTP-requests.
474//
475//// if (m_log.IsDebugEnabled)
476//// {
477//// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ ";
478//// foreach (object key in request.Keys)
479//// {
480//// debug += key.ToString() + "=" + request[key].ToString() + " ";
481//// }
482//// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
483//// }
484//
485// Queue<OSD> queue = TryGetQueue(agentID);
486// OSD element;
487//
488// lock (queue)
489// element = queue.Dequeue(); // 15s timeout
490//
491// Hashtable responsedata = new Hashtable();
492//
493// int thisID = 0;
494// lock (m_ids)
495// thisID = m_ids[agentID];
496//
497// if (element == null)
498// {
499// //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName);
500// if (thisID == -1) // close-request
501// {
502// m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName);
503// responsedata["int_response_code"] = 404; //501; //410; //404;
504// responsedata["content_type"] = "text/plain";
505// responsedata["keepalive"] = false;
506// responsedata["str_response_string"] = "Closed EQG";
507// return responsedata;
508// }
509// responsedata["int_response_code"] = 502;
510// responsedata["content_type"] = "text/plain";
511// responsedata["keepalive"] = false;
512// responsedata["str_response_string"] = "Upstream error: ";
513// responsedata["error_status_text"] = "Upstream error:";
514// responsedata["http_protocol_version"] = "HTTP/1.0";
515// return responsedata;
516// }
517//
518// OSDArray array = new OSDArray();
519// if (element == null) // didn't have an event in 15s
520// {
521// // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
522// array.Add(EventQueueHelper.KeepAliveEvent());
523// //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
524// }
525// else
526// {
527// array.Add(element);
528//
529// if (element is OSDMap)
530// {
531// OSDMap ev = (OSDMap)element;
532// m_log.DebugFormat(
533// "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
534// ev["message"], m_scene.GetScenePresence(agentID).Name);
535// }
536//
537// lock (queue)
538// {
539// while (queue.Count > 0)
540// {
541// element = queue.Dequeue();
542//
543// if (element is OSDMap)
544// {
545// OSDMap ev = (OSDMap)element;
546// m_log.DebugFormat(
547// "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
548// ev["message"], m_scene.GetScenePresence(agentID).Name);
549// }
550//
551// array.Add(element);
552// thisID++;
553// }
554// }
555// }
556//
557// OSDMap events = new OSDMap();
558// events.Add("events", array);
559//
560// events.Add("id", new OSDInteger(thisID));
561// lock (m_ids)
562// {
563// m_ids[agentID] = thisID + 1;
564// }
565//
566// responsedata["int_response_code"] = 200;
567// responsedata["content_type"] = "application/xml";
568// responsedata["keepalive"] = false;
569// responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
570//
571// m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
572//
573// return responsedata;
574// }
575
576// public Hashtable EventQueuePath2(Hashtable request)
577// {
578// string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/","");
579// // pull off the last "/" in the path.
580// Hashtable responsedata = new Hashtable();
581// capuuid = capuuid.Substring(0, capuuid.Length - 1);
582// capuuid = capuuid.Replace("/CAPS/EQG/", "");
583// UUID AvatarID = UUID.Zero;
584// UUID capUUID = UUID.Zero;
585//
586// // parse the path and search for the avatar with it registered
587// if (UUID.TryParse(capuuid, out capUUID))
588// {
589// lock (m_QueueUUIDAvatarMapping)
590// {
591// if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
592// {
593// AvatarID = m_QueueUUIDAvatarMapping[capUUID];
594// }
595// }
596//
597// if (AvatarID != UUID.Zero)
598// {
599// return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID));
600// }
601// else
602// {
603// responsedata["int_response_code"] = 404;
604// responsedata["content_type"] = "text/plain";
605// responsedata["keepalive"] = false;
606// responsedata["str_response_string"] = "Not Found";
607// responsedata["error_status_text"] = "Not Found";
608// responsedata["http_protocol_version"] = "HTTP/1.0";
609// return responsedata;
610// // return 404
611// }
612// }
613// else
614// {
615// responsedata["int_response_code"] = 404;
616// responsedata["content_type"] = "text/plain";
617// responsedata["keepalive"] = false;
618// responsedata["str_response_string"] = "Not Found";
619// responsedata["error_status_text"] = "Not Found";
620// responsedata["http_protocol_version"] = "HTTP/1.0";
621// return responsedata;
622// // return 404
623// }
624// }
625
626 public OSD EventQueueFallBack(string path, OSD request, string endpoint)
627 {
628 // This is a fallback element to keep the client from loosing EventQueueGet
629 // Why does CAPS fail sometimes!?
630 m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!");
631 string capuuid = path.Replace("/CAPS/EQG/","");
632 capuuid = capuuid.Substring(0, capuuid.Length - 1);
633
634// UUID AvatarID = UUID.Zero;
635 UUID capUUID = UUID.Zero;
636 if (UUID.TryParse(capuuid, out capUUID))
637 {
638/* Don't remove this yet code cleaners!
639 * Still testing this!
640 *
641 lock (m_QueueUUIDAvatarMapping)
642 {
643 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
644 {
645 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
646 }
647 }
648
649
650 if (AvatarID != UUID.Zero)
651 {
652 // Repair the CAP!
653 //OpenSim.Framework.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID);
654 //string capsBase = "/CAPS/EQG/";
655 //caps.RegisterHandler("EventQueueGet",
656 //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/",
657 //delegate(Hashtable m_dhttpMethod)
658 //{
659 // return ProcessQueue(m_dhttpMethod, AvatarID, caps);
660 //}));
661 // start new ID sequence.
662 Random rnd = new Random(System.Environment.TickCount);
663 lock (m_ids)
664 {
665 if (!m_ids.ContainsKey(AvatarID))
666 m_ids.Add(AvatarID, rnd.Next(30000000));
667 }
668
669
670 int thisID = 0;
671 lock (m_ids)
672 thisID = m_ids[AvatarID];
673
674 BlockingLLSDQueue queue = GetQueue(AvatarID);
675 OSDArray array = new OSDArray();
676 LLSD element = queue.Dequeue(15000); // 15s timeout
677 if (element == null)
678 {
679
680 array.Add(EventQueueHelper.KeepAliveEvent());
681 }
682 else
683 {
684 array.Add(element);
685 while (queue.Count() > 0)
686 {
687 array.Add(queue.Dequeue(1));
688 thisID++;
689 }
690 }
691 OSDMap events = new OSDMap();
692 events.Add("events", array);
693
694 events.Add("id", new LLSDInteger(thisID));
695
696 lock (m_ids)
697 {
698 m_ids[AvatarID] = thisID + 1;
699 }
700
701 return events;
702 }
703 else
704 {
705 return new LLSD();
706 }
707*
708*/
709 }
710 else
711 {
712 //return new LLSD();
713 }
714
715 return new OSDString("shutdown404!");
716 }
717
718 public void DisableSimulator(ulong handle, UUID avatarID) 500 public void DisableSimulator(ulong handle, UUID avatarID)
719 { 501 {
720 OSD item = EventQueueHelper.DisableSimulator(handle); 502 OSD item = EventQueueHelper.DisableSimulator(handle);
@@ -827,4 +609,4 @@ namespace OpenSim.Region.ClientStack.Linden
827 Enqueue(item, avatarID); 609 Enqueue(item, avatarID);
828 } 610 }
829 } 611 }
830} \ No newline at end of file 612}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
index 384af74..799ad0b 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -76,9 +76,9 @@ namespace OpenSim.Region.ClientStack.Linden
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", OSD.FromInteger(endPoint.Port));
80 llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint) regionSizeX)); 80 llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
81 llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint) regionSizeY)); 81 llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
82 82
83 OSDArray arr = new OSDArray(1); 83 OSDArray arr = new OSDArray(1);
84 arr.Add(llsdSimInfo); 84 arr.Add(llsdSimInfo);
@@ -157,6 +157,12 @@ namespace OpenSim.Region.ClientStack.Linden
157 uint locationID, uint flags, string capsURL, UUID agentID, 157 uint locationID, uint flags, string capsURL, UUID agentID,
158 int regionSizeX, int regionSizeY) 158 int regionSizeX, int regionSizeY)
159 { 159 {
160 // not sure why flags get overwritten here
161 if ((flags & (uint)TeleportFlags.IsFlying) != 0)
162 flags = (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.IsFlying;
163 else
164 flags = (uint)TeleportFlags.ViaLocation;
165
160 OSDMap info = new OSDMap(); 166 OSDMap info = new OSDMap();
161 info.Add("AgentID", OSD.FromUUID(agentID)); 167 info.Add("AgentID", OSD.FromUUID(agentID));
162 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this? 168 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this?
@@ -165,7 +171,8 @@ namespace OpenSim.Region.ClientStack.Linden
165 info.Add("SimAccess", OSD.FromInteger(simAccess)); 171 info.Add("SimAccess", OSD.FromInteger(simAccess));
166 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes())); 172 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
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
175 info.Add("TeleportFlags", OSD.FromUInteger(flags));
169 info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX)); 176 info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX));
170 info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY)); 177 info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY));
171 178
@@ -204,8 +211,8 @@ namespace OpenSim.Region.ClientStack.Linden
204 {"sim-ip-and-port", new OSDString(simIpAndPort)}, 211 {"sim-ip-and-port", new OSDString(simIpAndPort)},
205 {"seed-capability", new OSDString(seedcap)}, 212 {"seed-capability", new OSDString(seedcap)},
206 {"region-handle", OSD.FromULong(regionHandle)}, 213 {"region-handle", OSD.FromULong(regionHandle)},
207 {"region-size-x", OSD.FromInteger(regionSizeX)}, 214 {"region-size-x", OSD.FromUInteger((uint)regionSizeX)},
208 {"region-size-y", OSD.FromInteger(regionSizeY)} 215 {"region-size-y", OSD.FromUInteger((uint)regionSizeY)}
209 }; 216 };
210 217
211 return BuildEvent("EstablishAgentCommunication", body); 218 return BuildEvent("EstablishAgentCommunication", body);
@@ -412,7 +419,7 @@ namespace OpenSim.Region.ClientStack.Linden
412 public static OSD partPhysicsProperties(uint localID, byte physhapetype, 419 public static OSD partPhysicsProperties(uint localID, byte physhapetype,
413 float density, float friction, float bounce, float gravmod) 420 float density, float friction, float bounce, float gravmod)
414 { 421 {
415 422
416 OSDMap physinfo = new OSDMap(6); 423 OSDMap physinfo = new OSDMap(6);
417 physinfo["LocalID"] = localID; 424 physinfo["LocalID"] = localID;
418 physinfo["Density"] = density; 425 physinfo["Density"] = density;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index f57d857..b5a70040 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -27,11 +27,14 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Collections.Specialized; 31using System.Collections.Specialized;
31using System.Reflection; 32using System.Reflection;
32using System.IO; 33using System.IO;
34using System.Threading;
33using System.Web; 35using System.Web;
34using Mono.Addins; 36using Mono.Addins;
37using OpenSim.Framework.Monitoring;
35using log4net; 38using log4net;
36using Nini.Config; 39using Nini.Config;
37using OpenMetaverse; 40using OpenMetaverse;
@@ -57,12 +60,50 @@ namespace OpenSim.Region.ClientStack.Linden
57 private IAssetService m_AssetService; 60 private IAssetService m_AssetService;
58 private bool m_Enabled = true; 61 private bool m_Enabled = true;
59 private string m_URL; 62 private string m_URL;
63
60 private string m_URL2; 64 private string m_URL2;
61 private string m_RedirectURL = null; 65 private string m_RedirectURL = null;
62 private string m_RedirectURL2 = null; 66 private string m_RedirectURL2 = null;
67
68 struct aPollRequest
69 {
70 public PollServiceMeshEventArgs thepoll;
71 public UUID reqID;
72 public Hashtable request;
73 }
74
75 public class aPollResponse
76 {
77 public Hashtable response;
78 public int bytes;
79 public int lod;
80 }
81
82
83 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
84
85 private static GetMeshHandler m_getMeshHandler;
86
87 private IAssetService m_assetService = null;
88
89 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
90 private static Thread[] m_workerThreads = null;
91
92 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
93 new OpenMetaverse.BlockingQueue<aPollRequest>();
94
95 private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
96
63 97
64 #region Region Module interfaceBase Members 98 #region Region Module interfaceBase Members
65 99
100 ~GetMeshModule()
101 {
102 foreach (Thread t in m_workerThreads)
103 Watchdog.AbortThread(t.ManagedThreadId);
104
105 }
106
66 public Type ReplaceableInterface 107 public Type ReplaceableInterface
67 { 108 {
68 get { return null; } 109 get { return null; }
@@ -87,6 +128,7 @@ namespace OpenSim.Region.ClientStack.Linden
87 if (m_URL2 != string.Empty) 128 if (m_URL2 != string.Empty)
88 { 129 {
89 m_Enabled = true; 130 m_Enabled = true;
131
90 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL"); 132 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL");
91 } 133 }
92 } 134 }
@@ -97,6 +139,8 @@ namespace OpenSim.Region.ClientStack.Linden
97 return; 139 return;
98 140
99 m_scene = pScene; 141 m_scene = pScene;
142
143 m_assetService = pScene.AssetService;
100 } 144 }
101 145
102 public void RemoveRegion(Scene scene) 146 public void RemoveRegion(Scene scene)
@@ -105,6 +149,9 @@ namespace OpenSim.Region.ClientStack.Linden
105 return; 149 return;
106 150
107 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 151 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
152 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
153 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
154
108 m_scene = null; 155 m_scene = null;
109 } 156 }
110 157
@@ -115,6 +162,27 @@ namespace OpenSim.Region.ClientStack.Linden
115 162
116 m_AssetService = m_scene.RequestModuleInterface<IAssetService>(); 163 m_AssetService = m_scene.RequestModuleInterface<IAssetService>();
117 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 164 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
165 // We'll reuse the same handler for all requests.
166 m_getMeshHandler = new GetMeshHandler(m_assetService);
167 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
168 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
169
170 if (m_workerThreads == null)
171 {
172 m_workerThreads = new Thread[2];
173
174 for (uint i = 0; i < 2; i++)
175 {
176 m_workerThreads[i] = WorkManager.StartThread(DoMeshRequests,
177 String.Format("MeshWorkerThread{0}", i),
178 ThreadPriority.Normal,
179 false,
180 false,
181 null,
182 int.MaxValue);
183 }
184 }
185
118 } 186 }
119 187
120 188
@@ -124,44 +192,346 @@ namespace OpenSim.Region.ClientStack.Linden
124 192
125 #endregion 193 #endregion
126 194
195 private void DoMeshRequests()
196 {
197 while (true)
198 {
199 aPollRequest poolreq = m_queue.Dequeue();
127 200
128 public void RegisterCaps(UUID agentID, Caps caps) 201 poolreq.thepoll.Process(poolreq);
202 }
203 }
204
205 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
206 public void ThrottleUpdate(ScenePresence p)
207 {
208 UUID user = p.UUID;
209 int imagethrottle = p.ControllingClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset);
210 PollServiceMeshEventArgs args;
211 if (m_pollservices.TryGetValue(user, out args))
212 {
213 args.UpdateThrottle(imagethrottle, p);
214 }
215 }
216
217 private class PollServiceMeshEventArgs : PollServiceEventArgs
129 { 218 {
130 UUID capID = UUID.Random(); 219 private List<Hashtable> requests =
131 bool getMeshRegistered = false; 220 new List<Hashtable>();
221 private Dictionary<UUID, aPollResponse> responses =
222 new Dictionary<UUID, aPollResponse>();
132 223
133 if (m_URL == string.Empty) 224 private Scene m_scene;
225 private MeshCapsDataThrottler m_throttler;
226 public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
227 base(null, uri, null, null, null, pId, int.MaxValue)
134 { 228 {
229 m_scene = scene;
230 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
231 // x is request id, y is userid
232 HasEvents = (x, y) =>
233 {
234 lock (responses)
235 {
236 bool ret = m_throttler.hasEvents(x, responses);
237 m_throttler.ProcessTime();
238 return ret;
239
240 }
241 };
242 GetEvents = (x, y) =>
243 {
244 lock (responses)
245 {
246 try
247 {
248 return responses[x].response;
249 }
250 finally
251 {
252 m_throttler.ProcessTime();
253 responses.Remove(x);
254 }
255 }
256 };
257 // x is request id, y is request data hashtable
258 Request = (x, y) =>
259 {
260 aPollRequest reqinfo = new aPollRequest();
261 reqinfo.thepoll = this;
262 reqinfo.reqID = x;
263 reqinfo.request = y;
264
265 m_queue.Enqueue(reqinfo);
266 };
267
268 // this should never happen except possible on shutdown
269 NoEvents = (x, y) =>
270 {
271 /*
272 lock (requests)
273 {
274 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
275 requests.Remove(request);
276 }
277 */
278 Hashtable response = new Hashtable();
279
280 response["int_response_code"] = 500;
281 response["str_response_string"] = "Script timeout";
282 response["content_type"] = "text/plain";
283 response["keepalive"] = false;
284 response["reusecontext"] = false;
285
286 return response;
287 };
288 }
289
290 public void Process(aPollRequest requestinfo)
291 {
292 Hashtable response;
293
294 UUID requestID = requestinfo.reqID;
295
296 // If the avatar is gone, don't bother to get the texture
297 if (m_scene.GetScenePresence(Id) == null)
298 {
299 response = new Hashtable();
300
301 response["int_response_code"] = 500;
302 response["str_response_string"] = "Script timeout";
303 response["content_type"] = "text/plain";
304 response["keepalive"] = false;
305 response["reusecontext"] = false;
306
307 lock (responses)
308 responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 };
309
310 return;
311 }
312
313 response = m_getMeshHandler.Handle(requestinfo.request);
314 lock (responses)
315 {
316 responses[requestID] = new aPollResponse()
317 {
318 bytes = (int)response["int_bytes"],
319 lod = (int)response["int_lod"],
320 response = response
321 };
135 322
323 }
324 m_throttler.ProcessTime();
136 } 325 }
137 else if (m_URL == "localhost") 326
327 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
138 { 328 {
139 getMeshRegistered = true; 329 m_throttler.UpdateThrottle(pimagethrottle, p);
140 caps.RegisterHandler( 330 }
141 "GetMesh", 331 }
142 new GetMeshHandler("/CAPS/" + capID + "/", m_AssetService, "GetMesh", agentID.ToString(), m_RedirectURL)); 332
333 public void RegisterCaps(UUID agentID, Caps caps)
334 {
335// UUID capID = UUID.Random();
336 if (m_URL == "localhost")
337 {
338 string capUrl = "/CAPS/" + UUID.Random() + "/";
339
340 // Register this as a poll service
341 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
342
343 args.Type = PollServiceEventArgs.EventType.Mesh;
344 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
345
346 string hostName = m_scene.RegionInfo.ExternalHostName;
347 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
348 string protocol = "http";
349
350 if (MainServer.Instance.UseSSL)
351 {
352 hostName = MainServer.Instance.SSLCommonName;
353 port = MainServer.Instance.SSLPort;
354 protocol = "https";
355 }
356 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
357 m_pollservices[agentID] = args;
358 m_capsDict[agentID] = capUrl;
143 } 359 }
144 else 360 else
145 { 361 {
146 caps.RegisterHandler("GetMesh", m_URL); 362 caps.RegisterHandler("GetMesh", m_URL);
147 } 363 }
364 }
365
366 private void DeregisterCaps(UUID agentID, Caps caps)
367 {
368 string capUrl;
369 PollServiceMeshEventArgs args;
370 if (m_capsDict.TryGetValue(agentID, out capUrl))
371 {
372 MainServer.Instance.RemoveHTTPHandler("", capUrl);
373 m_capsDict.Remove(agentID);
374 }
375 if (m_pollservices.TryGetValue(agentID, out args))
376 {
377 m_pollservices.Remove(agentID);
378 }
379 }
380
381 internal sealed class MeshCapsDataThrottler
382 {
383
384 private volatile int currenttime = 0;
385 private volatile int lastTimeElapsed = 0;
386 private volatile int BytesSent = 0;
387 private int Lod3 = 0;
388 private int Lod2 = 0;
389 private int Lod1 = 0;
390 private int UserSetThrottle = 0;
391 private int UDPSetThrottle = 0;
392 private int CapSetThrottle = 0;
393 private float CapThrottleDistributon = 0.30f;
394 private readonly Scene m_scene;
395 private ThrottleOutPacketType Throttle;
396 private readonly UUID User;
397
398 public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
399 {
400 ThrottleBytes = pBytes;
401 lastTimeElapsed = Util.EnvironmentTickCount();
402 Throttle = ThrottleOutPacketType.Asset;
403 m_scene = pScene;
404 User = puser;
405 }
406
407
408 public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
409 {
410 const float ThirtyPercent = 0.30f;
411 const float FivePercent = 0.05f;
412 PassTime();
413 // Note, this is called IN LOCK
414 bool haskey = responses.ContainsKey(key);
415
416 if (responses.Count > 2)
417 {
418 SplitThrottle(ThirtyPercent);
419 }
420 else
421 {
422 SplitThrottle(FivePercent);
423 }
148 424
149 if(m_URL2 == string.Empty) 425 if (!haskey)
426 {
427 return false;
428 }
429 aPollResponse response;
430 if (responses.TryGetValue(key, out response))
431 {
432 float LOD3Over = (((ThrottleBytes*CapThrottleDistributon)%50000) + 1);
433 float LOD2Over = (((ThrottleBytes*CapThrottleDistributon)%10000) + 1);
434 // Normal
435 if (BytesSent + response.bytes <= ThrottleBytes)
436 {
437 BytesSent += response.bytes;
438
439 return true;
440 }
441 // Lod3 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
442 else if (response.bytes > ThrottleBytes && Lod3 <= ((LOD3Over < 1)? 1: LOD3Over) )
443 {
444 Interlocked.Increment(ref Lod3);
445 BytesSent += response.bytes;
446
447 return true;
448 }
449 // Lod2 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
450 else if (response.bytes > ThrottleBytes && Lod2 <= ((LOD2Over < 1) ? 1 : LOD2Over))
451 {
452 Interlocked.Increment(ref Lod2);
453 BytesSent += response.bytes;
454
455 return true;
456 }
457 else
458 {
459 return false;
460 }
461 }
462
463 return haskey;
464 }
465 public void SubtractBytes(int bytes,int lod)
466 {
467 BytesSent -= bytes;
468 }
469 private void SplitThrottle(float percentMultiplier)
150 { 470 {
151 471
472 if (CapThrottleDistributon != percentMultiplier) // don't switch it if it's already set at the % multipler
473 {
474 CapThrottleDistributon = percentMultiplier;
475 ScenePresence p;
476 if (m_scene.TryGetScenePresence(User, out p)) // If we don't get a user they're not here anymore.
477 {
478// AlterThrottle(UserSetThrottle, p);
479 UpdateThrottle(UserSetThrottle, p);
480 }
481 }
152 } 482 }
153 else if (m_URL2 == "localhost") 483
484 public void ProcessTime()
154 { 485 {
155 if (!getMeshRegistered) 486 PassTime();
487 }
488
489
490 private void PassTime()
491 {
492 currenttime = Util.EnvironmentTickCount();
493 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
494 //processTimeBasedActions(responses);
495 if (currenttime - timeElapsed >= 1000)
156 { 496 {
157 caps.RegisterHandler( 497 lastTimeElapsed = Util.EnvironmentTickCount();
158 "GetMesh2", 498 BytesSent -= ThrottleBytes;
159 new GetMeshHandler("/CAPS/" + capID + "/", m_AssetService, "GetMesh2", agentID.ToString(), m_RedirectURL2)); 499 if (BytesSent < 0) BytesSent = 0;
500 if (BytesSent < ThrottleBytes)
501 {
502 Lod3 = 0;
503 Lod2 = 0;
504 Lod1 = 0;
505 }
160 } 506 }
161 } 507 }
162 else 508 private void AlterThrottle(int setting, ScenePresence p)
509 {
510 p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting);
511 }
512
513 public int ThrottleBytes
163 { 514 {
164 caps.RegisterHandler("GetMesh2", m_URL2); 515 get { return CapSetThrottle; }
516 set { CapSetThrottle = value; }
517 }
518
519 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
520 {
521 // Client set throttle !
522 UserSetThrottle = pimagethrottle;
523 CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon);
524// UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon));
525
526 float udp = 1.0f - CapThrottleDistributon;
527 if(udp < 0.7f)
528 udp = 0.7f;
529 UDPSetThrottle = (int) ((float)pimagethrottle * udp);
530 if (CapSetThrottle < 4068)
531 CapSetThrottle = 4068; // at least two discovery mesh
532 p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle);
533 ProcessTime();
534
165 } 535 }
166 } 536 }
167 537
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index bb932f2..79a3458 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -27,18 +27,13 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Specialized; 30using System.Collections.Generic;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.Reflection; 31using System.Reflection;
34using System.IO; 32using System.Threading;
35using System.Web;
36using log4net; 33using log4net;
37using Nini.Config; 34using Nini.Config;
38using Mono.Addins; 35using Mono.Addins;
39using OpenMetaverse; 36using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenMetaverse.Imaging;
42using OpenSim.Framework; 37using OpenSim.Framework;
43using OpenSim.Framework.Servers; 38using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
@@ -47,6 +42,7 @@ using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
48using Caps = OpenSim.Framework.Capabilities.Caps; 43using Caps = OpenSim.Framework.Capabilities.Caps;
49using OpenSim.Capabilities.Handlers; 44using OpenSim.Capabilities.Handlers;
45using OpenSim.Framework.Monitoring;
50 46
51namespace OpenSim.Region.ClientStack.Linden 47namespace OpenSim.Region.ClientStack.Linden
52{ 48{
@@ -54,27 +50,54 @@ namespace OpenSim.Region.ClientStack.Linden
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
55 public class GetTextureModule : INonSharedRegionModule 51 public class GetTextureModule : INonSharedRegionModule
56 { 52 {
57// private static readonly ILog m_log = 53
58// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 struct aPollRequest
59 55 {
56 public PollServiceTextureEventArgs thepoll;
57 public UUID reqID;
58 public Hashtable request;
59 public bool send503;
60 }
61
62 public class aPollResponse
63 {
64 public Hashtable response;
65 public int bytes;
66 }
67
68
69 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
70
60 private Scene m_scene; 71 private Scene m_scene;
61 private IAssetService m_assetService;
62 72
63 private bool m_Enabled = false; 73 private static GetTextureHandler m_getTextureHandler;
74
75 private IAssetService m_assetService = null;
76
77 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
78 private static Thread[] m_workerThreads = null;
79
80 private string m_Url = "localhost";
81
82 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
83 new OpenMetaverse.BlockingQueue<aPollRequest>();
84
64 85
65 // TODO: Change this to a config option 86 // TODO: Change this to a config option
66 private string m_RedirectURL = null; 87 private string m_RedirectURL = null;
67 88
68 private string m_URL; 89 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
90
69 91
70 #region ISharedRegionModule Members 92 #region ISharedRegionModule Members
71 93
72 public void Initialise(IConfigSource source) 94 public void Initialise(IConfigSource source)
73 { 95 {
74 IConfig config = source.Configs["ClientStack.LindenCaps"]; 96 IConfig config = source.Configs["ClientStack.LindenCaps"];
97
75 if (config == null) 98 if (config == null)
76 return; 99 return;
77 100/*
78 m_URL = config.GetString("Cap_GetTexture", string.Empty); 101 m_URL = config.GetString("Cap_GetTexture", string.Empty);
79 // Cap doesn't exist 102 // Cap doesn't exist
80 if (m_URL != string.Empty) 103 if (m_URL != string.Empty)
@@ -82,32 +105,98 @@ namespace OpenSim.Region.ClientStack.Linden
82 m_Enabled = true; 105 m_Enabled = true;
83 m_RedirectURL = config.GetString("GetTextureRedirectURL"); 106 m_RedirectURL = config.GetString("GetTextureRedirectURL");
84 } 107 }
108*/
109 m_Url = config.GetString("Cap_GetTexture", "localhost");
85 } 110 }
86 111
87 public void AddRegion(Scene s) 112 public void AddRegion(Scene s)
88 { 113 {
89 if (!m_Enabled)
90 return;
91
92 m_scene = s; 114 m_scene = s;
115 m_assetService = s.AssetService;
93 } 116 }
94 117
95 public void RemoveRegion(Scene s) 118 public void RemoveRegion(Scene s)
96 { 119 {
97 if (!m_Enabled)
98 return;
99
100 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 120 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
121 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
122 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
101 m_scene = null; 123 m_scene = null;
102 } 124 }
103 125
104 public void RegionLoaded(Scene s) 126 public void RegionLoaded(Scene s)
105 { 127 {
106 if (!m_Enabled) 128 // We'll reuse the same handler for all requests.
107 return; 129 m_getTextureHandler = new GetTextureHandler(m_assetService);
108 130
109 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
110 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 131 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
132 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
133 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
134
135 if (m_workerThreads == null)
136 {
137 m_workerThreads = new Thread[2];
138
139 for (uint i = 0; i < 2; i++)
140 {
141 m_workerThreads[i] = WorkManager.StartThread(DoTextureRequests,
142 String.Format("TextureWorkerThread{0}", i),
143 ThreadPriority.Normal,
144 false,
145 false,
146 null,
147 int.MaxValue);
148 }
149 }
150 }
151 private int ExtractImageThrottle(byte[] pthrottles)
152 {
153
154 byte[] adjData;
155 int pos = 0;
156
157 if (!BitConverter.IsLittleEndian)
158 {
159 byte[] newData = new byte[7 * 4];
160 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
161
162 for (int i = 0; i < 7; i++)
163 Array.Reverse(newData, i * 4, 4);
164
165 adjData = newData;
166 }
167 else
168 {
169 adjData = pthrottles;
170 }
171
172 // 0.125f converts from bits to bytes
173 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
174 //pos += 4;
175 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
176 //pos += 4;
177 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
178 // pos += 4;
179 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
180 // pos += 4;
181 // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
182 // pos += 4;
183 pos = pos + 20;
184 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
185 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
186 return texture;
187 }
188
189 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
190 public void ThrottleUpdate(ScenePresence p)
191 {
192 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
193 UUID user = p.UUID;
194 int imagethrottle = ExtractImageThrottle(throttles);
195 PollServiceTextureEventArgs args;
196 if (m_pollservices.TryGetValue(user,out args))
197 {
198 args.UpdateThrottle(imagethrottle);
199 }
111 } 200 }
112 201
113 public void PostInitialise() 202 public void PostInitialise()
@@ -125,28 +214,295 @@ namespace OpenSim.Region.ClientStack.Linden
125 214
126 #endregion 215 #endregion
127 216
128 public void RegisterCaps(UUID agentID, Caps caps) 217 ~GetTextureModule()
218 {
219 foreach (Thread t in m_workerThreads)
220 Watchdog.AbortThread(t.ManagedThreadId);
221
222 }
223
224 private class PollServiceTextureEventArgs : PollServiceEventArgs
129 { 225 {
130 UUID capID = UUID.Random(); 226 private List<Hashtable> requests =
227 new List<Hashtable>();
228 private Dictionary<UUID, aPollResponse> responses =
229 new Dictionary<UUID, aPollResponse>();
131 230
132 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); 231 private Scene m_scene;
133 if (m_URL == "localhost") 232 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
233 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
234 base(null, "", null, null, null, pId, int.MaxValue)
134 { 235 {
135// m_log.DebugFormat("[GETTEXTURE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 236 m_scene = scene;
136 caps.RegisterHandler( 237 // x is request id, y is userid
137 "GetTexture", 238 HasEvents = (x, y) =>
138 new GetTextureHandler("/CAPS/" + capID + "/", m_assetService, "GetTexture", agentID.ToString(), m_RedirectURL)); 239 {
240 lock (responses)
241 {
242 bool ret = m_throttler.hasEvents(x, responses);
243 m_throttler.ProcessTime();
244 return ret;
245
246 }
247 };
248 GetEvents = (x, y) =>
249 {
250 lock (responses)
251 {
252 try
253 {
254 return responses[x].response;
255 }
256 finally
257 {
258 responses.Remove(x);
259 }
260 }
261 };
262 // x is request id, y is request data hashtable
263 Request = (x, y) =>
264 {
265 aPollRequest reqinfo = new aPollRequest();
266 reqinfo.thepoll = this;
267 reqinfo.reqID = x;
268 reqinfo.request = y;
269 reqinfo.send503 = false;
270
271 lock (responses)
272 {
273 if (responses.Count > 0)
274 {
275 if (m_queue.Count >= 4)
276 {
277 // Never allow more than 4 fetches to wait
278 reqinfo.send503 = true;
279 }
280 }
281 }
282 m_queue.Enqueue(reqinfo);
283 };
284
285 // this should never happen except possible on shutdown
286 NoEvents = (x, y) =>
287 {
288/*
289 lock (requests)
290 {
291 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
292 requests.Remove(request);
293 }
294*/
295 Hashtable response = new Hashtable();
296
297 response["int_response_code"] = 500;
298 response["str_response_string"] = "Script timeout";
299 response["content_type"] = "text/plain";
300 response["keepalive"] = false;
301 response["reusecontext"] = false;
302
303 return response;
304 };
139 } 305 }
140 else 306
307 public void Process(aPollRequest requestinfo)
308 {
309 Hashtable response;
310
311 UUID requestID = requestinfo.reqID;
312
313 if (requestinfo.send503)
314 {
315 response = new Hashtable();
316
317
318 response["int_response_code"] = 503;
319 response["str_response_string"] = "Throttled";
320 response["content_type"] = "text/plain";
321 response["keepalive"] = false;
322 response["reusecontext"] = false;
323
324 Hashtable headers = new Hashtable();
325 headers["Retry-After"] = 30;
326 response["headers"] = headers;
327
328 lock (responses)
329 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
330
331 return;
332 }
333
334 // If the avatar is gone, don't bother to get the texture
335 if (m_scene.GetScenePresence(Id) == null)
336 {
337 response = new Hashtable();
338
339 response["int_response_code"] = 500;
340 response["str_response_string"] = "Script timeout";
341 response["content_type"] = "text/plain";
342 response["keepalive"] = false;
343 response["reusecontext"] = false;
344
345 lock (responses)
346 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
347
348 return;
349 }
350
351 response = m_getTextureHandler.Handle(requestinfo.request);
352 lock (responses)
353 {
354 responses[requestID] = new aPollResponse()
355 {
356 bytes = (int) response["int_bytes"],
357 response = response
358 };
359
360 }
361 m_throttler.ProcessTime();
362 }
363
364 internal void UpdateThrottle(int pimagethrottle)
141 { 365 {
142// m_log.DebugFormat("[GETTEXTURE]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName); 366 m_throttler.ThrottleBytes = pimagethrottle;
367 }
368 }
369
370 private void RegisterCaps(UUID agentID, Caps caps)
371 {
372 if (m_Url == "localhost")
373 {
374 string capUrl = "/CAPS/" + UUID.Random() + "/";
375
376 // Register this as a poll service
377 PollServiceTextureEventArgs args = new PollServiceTextureEventArgs(agentID, m_scene);
378
379 args.Type = PollServiceEventArgs.EventType.Texture;
380 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
381
382 string hostName = m_scene.RegionInfo.ExternalHostName;
383 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
384 string protocol = "http";
385
386 if (MainServer.Instance.UseSSL)
387 {
388 hostName = MainServer.Instance.SSLCommonName;
389 port = MainServer.Instance.SSLPort;
390 protocol = "https";
391 }
143 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>(); 392 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
144 if (handler != null) 393 if (handler != null)
145 handler.RegisterExternalUserCapsHandler(agentID,caps,"GetTexture", m_URL); 394 handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", capUrl);
146 else 395 else
147 caps.RegisterHandler("GetTexture", m_URL); 396 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
397 m_pollservices[agentID] = args;
398 m_capsDict[agentID] = capUrl;
399 }
400 else
401 {
402 caps.RegisterHandler("GetTexture", m_Url);
148 } 403 }
149 } 404 }
150 405
406 private void DeregisterCaps(UUID agentID, Caps caps)
407 {
408 PollServiceTextureEventArgs args;
409
410 MainServer.Instance.RemoveHTTPHandler("", m_Url);
411 m_capsDict.Remove(agentID);
412
413 if (m_pollservices.TryGetValue(agentID, out args))
414 {
415 m_pollservices.Remove(agentID);
416 }
417 }
418
419 private void DoTextureRequests()
420 {
421 while (true)
422 {
423 aPollRequest poolreq = m_queue.Dequeue();
424
425 poolreq.thepoll.Process(poolreq);
426 }
427 }
428 internal sealed class CapsDataThrottler
429 {
430
431 private volatile int currenttime = 0;
432 private volatile int lastTimeElapsed = 0;
433 private volatile int BytesSent = 0;
434 private int oversizedImages = 0;
435 public CapsDataThrottler(int pBytes, int max, int min)
436 {
437 ThrottleBytes = pBytes;
438 lastTimeElapsed = Util.EnvironmentTickCount();
439 }
440 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses)
441 {
442 PassTime();
443 // Note, this is called IN LOCK
444 bool haskey = responses.ContainsKey(key);
445 if (!haskey)
446 {
447 return false;
448 }
449 GetTextureModule.aPollResponse response;
450 if (responses.TryGetValue(key, out response))
451 {
452 // This is any error response
453 if (response.bytes == 0)
454 return true;
455
456 // Normal
457 if (BytesSent + response.bytes <= ThrottleBytes)
458 {
459 BytesSent += response.bytes;
460 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false };
461 //m_actions.Add(timeBasedAction);
462 return true;
463 }
464 // Big textures
465 else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1))
466 {
467 Interlocked.Increment(ref oversizedImages);
468 BytesSent += response.bytes;
469 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false };
470 //m_actions.Add(timeBasedAction);
471 return true;
472 }
473 else
474 {
475 return false;
476 }
477 }
478
479 return haskey;
480 }
481
482 public void ProcessTime()
483 {
484 PassTime();
485 }
486
487 private void PassTime()
488 {
489 currenttime = Util.EnvironmentTickCount();
490 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
491 //processTimeBasedActions(responses);
492 if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000)
493 {
494 lastTimeElapsed = Util.EnvironmentTickCount();
495 BytesSent -= ThrottleBytes;
496 if (BytesSent < 0) BytesSent = 0;
497 if (BytesSent < ThrottleBytes)
498 {
499 oversizedImages = 0;
500 }
501 }
502 }
503 public int ThrottleBytes;
504 }
151 } 505 }
506
507
152} 508}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
index 45d33cd..1b68603 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
@@ -129,15 +129,15 @@ namespace OpenSim.Region.ClientStack.Linden
129// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request"); 129// m_log.DebugFormat("[MESH UPLOAD FLAG MODULE]: MeshUploadFlag request");
130 130
131 OSDMap data = new OSDMap(); 131 OSDMap data = new OSDMap();
132 ScenePresence sp = m_scene.GetScenePresence(agentID); 132// ScenePresence sp = m_scene.GetScenePresence(m_agentID);
133 data["username"] = sp.Firstname + "." + sp.Lastname; 133// data["username"] = sp.Firstname + "." + sp.Lastname;
134 data["display_name_next_update"] = new OSDDate(DateTime.Now); 134// data["display_name_next_update"] = new OSDDate(DateTime.Now);
135 data["legacy_first_name"] = sp.Firstname; 135// data["legacy_first_name"] = sp.Firstname;
136 data["mesh_upload_status"] = "valid"; 136 data["mesh_upload_status"] = "valid";
137 data["display_name"] = sp.Firstname + " " + sp.Lastname; 137// data["display_name"] = sp.Firstname + " " + sp.Lastname;
138 data["legacy_last_name"] = sp.Lastname; 138// data["legacy_last_name"] = sp.Lastname;
139 data["id"] = agentID; 139// data["id"] = m_agentID;
140 data["is_display_name_default"] = true; 140// data["is_display_name_default"] = true;
141 141
142 //Send back data 142 //Send back data
143 Hashtable responsedata = new Hashtable(); 143 Hashtable responsedata = new Hashtable();
@@ -148,4 +148,4 @@ namespace OpenSim.Region.ClientStack.Linden
148 return responsedata; 148 return responsedata;
149 } 149 }
150 } 150 }
151} \ No newline at end of file 151}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
deleted file mode 100644
index f69a0bb..0000000
--- a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs
+++ /dev/null
@@ -1,297 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using Mono.Addins;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Services.Interfaces;
45using Caps = OpenSim.Framework.Capabilities.Caps;
46using OpenSim.Framework.Capabilities;
47using PermissionMask = OpenSim.Framework.PermissionMask;
48
49namespace OpenSim.Region.ClientStack.Linden
50{
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "NewFileAgentInventoryVariablePriceModule")]
52 public class NewFileAgentInventoryVariablePriceModule : INonSharedRegionModule
53 {
54// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Scene m_scene;
57// private IAssetService m_assetService;
58 private bool m_dumpAssetsToFile = false;
59 private bool m_enabled = true;
60 private int m_levelUpload = 0;
61
62 #region Region Module interfaceBase Members
63
64
65 public Type ReplaceableInterface
66 {
67 get { return null; }
68 }
69
70 public void Initialise(IConfigSource source)
71 {
72 IConfig meshConfig = source.Configs["Mesh"];
73 if (meshConfig == null)
74 return;
75
76 m_enabled = meshConfig.GetBoolean("AllowMeshUpload", true);
77 m_levelUpload = meshConfig.GetInt("LevelUpload", 0);
78 }
79
80 public void AddRegion(Scene pScene)
81 {
82 m_scene = pScene;
83 }
84
85 public void RemoveRegion(Scene scene)
86 {
87
88 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
89 m_scene = null;
90 }
91
92 public void RegionLoaded(Scene scene)
93 {
94
95// m_assetService = m_scene.RequestModuleInterface<IAssetService>();
96 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
97 }
98
99 #endregion
100
101
102 #region Region Module interface
103
104
105
106 public void Close() { }
107
108 public string Name { get { return "NewFileAgentInventoryVariablePriceModule"; } }
109
110
111 public void RegisterCaps(UUID agentID, Caps caps)
112 {
113 if(!m_enabled)
114 return;
115
116 UUID capID = UUID.Random();
117
118// m_log.Debug("[NEW FILE AGENT INVENTORY VARIABLE PRICE]: /CAPS/" + capID);
119 caps.RegisterHandler(
120 "NewFileAgentInventoryVariablePrice",
121 new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>(
122 "POST",
123 "/CAPS/" + capID.ToString(),
124 req => NewAgentInventoryRequest(req, agentID),
125 "NewFileAgentInventoryVariablePrice",
126 agentID.ToString()));
127 }
128
129 #endregion
130
131 public LLSDNewFileAngentInventoryVariablePriceReplyResponse NewAgentInventoryRequest(LLSDAssetUploadRequest llsdRequest, UUID agentID)
132 {
133 //TODO: The Mesh uploader uploads many types of content. If you're going to implement a Money based limit
134 // you need to be aware of this
135
136 //if (llsdRequest.asset_type == "texture" ||
137 // llsdRequest.asset_type == "animation" ||
138 // llsdRequest.asset_type == "sound")
139 // {
140 // check user level
141
142 ScenePresence avatar = null;
143 IClientAPI client = null;
144 m_scene.TryGetScenePresence(agentID, out avatar);
145
146 if (avatar != null)
147 {
148 client = avatar.ControllingClient;
149
150 if (avatar.UserLevel < m_levelUpload)
151 {
152 if (client != null)
153 client.SendAgentAlertMessage("Unable to upload asset. Insufficient permissions.", false);
154
155 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
156 errorResponse.rsvp = "";
157 errorResponse.state = "error";
158 return errorResponse;
159 }
160 }
161
162 // check funds
163 IMoneyModule mm = m_scene.RequestModuleInterface<IMoneyModule>();
164
165 if (mm != null)
166 {
167 if (!mm.UploadCovered(agentID, mm.UploadCharge))
168 {
169 if (client != null)
170 client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false);
171
172 LLSDNewFileAngentInventoryVariablePriceReplyResponse errorResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
173 errorResponse.rsvp = "";
174 errorResponse.state = "error";
175 return errorResponse;
176 }
177 }
178
179 // }
180
181 string assetName = llsdRequest.name;
182 string assetDes = llsdRequest.description;
183 string capsBase = "/CAPS/NewFileAgentInventoryVariablePrice/";
184 UUID newAsset = UUID.Random();
185 UUID newInvItem = UUID.Random();
186 UUID parentFolder = llsdRequest.folder_id;
187 string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000") + "/";
188
189 AssetUploader uploader =
190 new AssetUploader(assetName, assetDes, newAsset, newInvItem, parentFolder, llsdRequest.inventory_type,
191 llsdRequest.asset_type, capsBase + uploaderPath, MainServer.Instance, m_dumpAssetsToFile);
192
193 MainServer.Instance.AddStreamHandler(
194 new BinaryStreamHandler(
195 "POST",
196 capsBase + uploaderPath,
197 uploader.uploaderCaps,
198 "NewFileAgentInventoryVariablePrice",
199 agentID.ToString()));
200
201 string protocol = "http://";
202
203 if (MainServer.Instance.UseSSL)
204 protocol = "https://";
205
206 string uploaderURL = protocol + m_scene.RegionInfo.ExternalHostName + ":" + MainServer.Instance.Port.ToString() + capsBase +
207 uploaderPath;
208
209
210 LLSDNewFileAngentInventoryVariablePriceReplyResponse uploadResponse = new LLSDNewFileAngentInventoryVariablePriceReplyResponse();
211
212 uploadResponse.rsvp = uploaderURL;
213 uploadResponse.state = "upload";
214 uploadResponse.resource_cost = 0;
215 uploadResponse.upload_price = 0;
216
217 uploader.OnUpLoad += //UploadCompleteHandler;
218
219 delegate(
220 string passetName, string passetDescription, UUID passetID,
221 UUID pinventoryItem, UUID pparentFolder, byte[] pdata, string pinventoryType,
222 string passetType)
223 {
224 UploadCompleteHandler(passetName, passetDescription, passetID,
225 pinventoryItem, pparentFolder, pdata, pinventoryType,
226 passetType,agentID);
227 };
228
229 return uploadResponse;
230 }
231
232 public void UploadCompleteHandler(string assetName, string assetDescription, UUID assetID,
233 UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType,
234 string assetType,UUID AgentID)
235 {
236// m_log.DebugFormat(
237// "[NEW FILE AGENT INVENTORY VARIABLE PRICE MODULE]: Upload complete for {0}", inventoryItem);
238
239 sbyte assType = 0;
240 sbyte inType = 0;
241
242 if (inventoryType == "sound")
243 {
244 inType = 1;
245 assType = 1;
246 }
247 else if (inventoryType == "animation")
248 {
249 inType = 19;
250 assType = 20;
251 }
252 else if (inventoryType == "wearable")
253 {
254 inType = 18;
255 switch (assetType)
256 {
257 case "bodypart":
258 assType = 13;
259 break;
260 case "clothing":
261 assType = 5;
262 break;
263 }
264 }
265 else if (inventoryType == "mesh")
266 {
267 inType = (sbyte)InventoryType.Mesh;
268 assType = (sbyte)AssetType.Mesh;
269 }
270
271 AssetBase asset;
272 asset = new AssetBase(assetID, assetName, assType, AgentID.ToString());
273 asset.Data = data;
274
275 if (m_scene.AssetService != null)
276 m_scene.AssetService.Store(asset);
277
278 InventoryItemBase item = new InventoryItemBase();
279 item.Owner = AgentID;
280 item.CreatorId = AgentID.ToString();
281 item.ID = inventoryItem;
282 item.AssetID = asset.FullID;
283 item.Description = assetDescription;
284 item.Name = assetName;
285 item.AssetType = assType;
286 item.InvType = inType;
287 item.Folder = parentFolder;
288 item.CurrentPermissions
289 = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer);
290 item.BasePermissions = (uint)PermissionMask.All;
291 item.EveryOnePermissions = 0;
292 item.NextPermissions = (uint)PermissionMask.All;
293 item.CreationDate = Util.UnixTimeSinceEpoch();
294 m_scene.AddInventoryItem(item);
295 }
296 }
297}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index a133a69..5196368 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -64,6 +64,8 @@ namespace OpenSim.Region.ClientStack.Linden
64 private Commands m_commands = new Commands(); 64 private Commands m_commands = new Commands();
65 public ICommands Commands { get { return m_commands; } } 65 public ICommands Commands { get { return m_commands; } }
66 66
67 public event ConsoleMessage OnConsoleMessage;
68
67 public void Initialise(IConfigSource source) 69 public void Initialise(IConfigSource source)
68 { 70 {
69 m_commands.AddCommand( "Help", false, "help", "help [<item>]", "Display help on a particular command or on a list of commands in a category", Help); 71 m_commands.AddCommand( "Help", false, "help", "help [<item>]", "Display help on a particular command or on a list of commands in a category", Help);
@@ -102,7 +104,7 @@ namespace OpenSim.Region.ClientStack.Linden
102 104
103 public void RegisterCaps(UUID agentID, Caps caps) 105 public void RegisterCaps(UUID agentID, Caps caps)
104 { 106 {
105 if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID)) 107 if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID) && !m_scene.Permissions.IsGod(agentID))
106 return; 108 return;
107 109
108 UUID capID = UUID.Random(); 110 UUID capID = UUID.Random();
@@ -118,6 +120,11 @@ namespace OpenSim.Region.ClientStack.Linden
118 OSD osd = OSD.FromString(message); 120 OSD osd = OSD.FromString(message);
119 121
120 m_eventQueue.Enqueue(EventQueueHelper.BuildEvent("SimConsoleResponse", osd), agentID); 122 m_eventQueue.Enqueue(EventQueueHelper.BuildEvent("SimConsoleResponse", osd), agentID);
123
124 ConsoleMessage handlerConsoleMessage = OnConsoleMessage;
125
126 if (handlerConsoleMessage != null)
127 handlerConsoleMessage( agentID, message);
121 } 128 }
122 129
123 public bool RunCommand(string command, UUID invokerID) 130 public bool RunCommand(string command, UUID invokerID)
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index e258bcb..d07f66e 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.Linden
155 m_features["MeshRezEnabled"] = true; 155 m_features["MeshRezEnabled"] = true;
156 m_features["MeshUploadEnabled"] = true; 156 m_features["MeshUploadEnabled"] = true;
157 m_features["MeshXferEnabled"] = true; 157 m_features["MeshXferEnabled"] = true;
158
158 m_features["PhysicsMaterialsEnabled"] = true; 159 m_features["PhysicsMaterialsEnabled"] = true;
159 160
160 OSDMap typesMap = new OSDMap(); 161 OSDMap typesMap = new OSDMap();
@@ -173,6 +174,10 @@ namespace OpenSim.Region.ClientStack.Linden
173 else 174 else
174 extrasMap = new OSDMap(); 175 extrasMap = new OSDMap();
175 176
177 extrasMap["AvatarSkeleton"] = true;
178 extrasMap["AnimationSet"] = true;
179
180 // TODO: Take these out of here into their respective modules, like map-server-url
176 if (m_SearchURL != string.Empty) 181 if (m_SearchURL != string.Empty)
177 extrasMap["search-server-url"] = m_SearchURL; 182 extrasMap["search-server-url"] = m_SearchURL;
178 if (!string.IsNullOrEmpty(m_DestinationGuideURL)) 183 if (!string.IsNullOrEmpty(m_DestinationGuideURL))
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs
index dd4a691..db16ccb 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Tests/WebFetchInvDescModuleTests.cs
@@ -52,6 +52,7 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap;
52 52
53namespace OpenSim.Region.ClientStack.Linden.Caps.Tests 53namespace OpenSim.Region.ClientStack.Linden.Caps.Tests
54{ 54{
55 /*
55 [TestFixture] 56 [TestFixture]
56 public class WebFetchInvDescModuleTests : OpenSimTestCase 57 public class WebFetchInvDescModuleTests : OpenSimTestCase
57 { 58 {
@@ -156,4 +157,5 @@ namespace OpenSim.Region.ClientStack.Linden.Caps.Tests
156 Assert.That((int)folderOsd["descendents"], Is.EqualTo(16)); 157 Assert.That((int)folderOsd["descendents"], Is.EqualTo(16));
157 } 158 }
158 } 159 }
160 */
159} \ No newline at end of file 161} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index 8cdebcd..8fd8d1f 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -66,14 +66,19 @@ namespace OpenSim.Region.ClientStack.Linden
66 private bool m_persistBakedTextures; 66 private bool m_persistBakedTextures;
67 67
68 private IBakedTextureModule m_BakedTextureModule; 68 private IBakedTextureModule m_BakedTextureModule;
69 private string m_URL;
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);
75
76
77 } 82 }
78 83
79 public void AddRegion(Scene s) 84 public void AddRegion(Scene s)
@@ -89,9 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden
89 s.EventManager.OnRemovePresence -= DeRegisterPresence; 94 s.EventManager.OnRemovePresence -= DeRegisterPresence;
90 m_BakedTextureModule = null; 95 m_BakedTextureModule = null;
91 m_scene = null; 96 m_scene = null;
92 } 97 }
93
94
95 98
96 public void RegionLoaded(Scene s) 99 public void RegionLoaded(Scene s)
97 { 100 {
@@ -103,44 +106,52 @@ namespace OpenSim.Region.ClientStack.Linden
103 106
104 private void DeRegisterPresence(UUID agentId) 107 private void DeRegisterPresence(UUID agentId)
105 { 108 {
106 ScenePresence presence = null;
107 if (m_scene.TryGetScenePresence(agentId, out presence))
108 {
109 presence.ControllingClient.OnSetAppearance -= CaptureAppearanceSettings;
110 }
111
112 } 109 }
113 110
114 private void RegisterNewPresence(ScenePresence presence) 111 private void RegisterNewPresence(ScenePresence presence)
115 { 112 {
116 presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings; 113// presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings;
117
118 } 114 }
119 115
120 private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) 116/* not in use. work done in AvatarFactoryModule ValidateBakedTextureCache() and UpdateBakedTextureCache()
121 { 117 private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems)
122 int maxCacheitemsLoop = cacheItems.Length;
123 if (maxCacheitemsLoop > AvatarWearable.MAX_WEARABLES)
124 {
125 maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES;
126 m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES);
127 }
128
129 m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
130 if (cacheItems.Length > 0)
131 {
132// m_log.Debug("[Cacheitems]: " + cacheItems.Length);
133// for (int iter = 0; iter < maxCacheitemsLoop; iter++)
134// {
135// m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
136// cacheItems[iter].TextureID);
137// }
138
139 ScenePresence p = null;
140 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p))
141 { 118 {
119 // if cacheItems.Length > 0 viewer is giving us current textures information.
120 // baked ones should had been uploaded and in assets cache as local itens
121
122
123 if (cacheItems.Length == 0)
124 return; // no textures information, nothing to do
125
126 ScenePresence p = null;
127 if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out p))
128 return; // what are we doing if there is no presence to cache for?
129
130 if (p.IsDeleted)
131 return; // does this really work?
132
133 int maxCacheitemsLoop = cacheItems.Length;
134 if (maxCacheitemsLoop > 20)
135 {
136 maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES;
137 m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES);
138 }
139
140 m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
141
142
143 // some nice debug
144 m_log.Debug("[Cacheitems]: " + cacheItems.Length);
145 for (int iter = 0; iter < maxCacheitemsLoop; iter++)
146 {
147 m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
148 cacheItems[iter].TextureID);
149 }
150
151 // p.Appearance.WearableCacheItems is in memory primary cashID to textures mapper
142 152
143 WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems; 153 WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems;
154
144 if (existingitems == null) 155 if (existingitems == null)
145 { 156 {
146 if (m_BakedTextureModule != null) 157 if (m_BakedTextureModule != null)
@@ -154,38 +165,22 @@ namespace OpenSim.Region.ClientStack.Linden
154 p.Appearance.WearableCacheItems = savedcache; 165 p.Appearance.WearableCacheItems = savedcache;
155 p.Appearance.WearableCacheItemsDirty = false; 166 p.Appearance.WearableCacheItemsDirty = false;
156 } 167 }
157
158 }
159 /*
160 * The following Catch types DO NOT WORK with m_BakedTextureModule.Get
161 * it jumps to the General Packet Exception Handler if you don't catch Exception!
162 *
163 catch (System.Net.Sockets.SocketException)
164 {
165 cacheItems = null;
166 } 168 }
167 catch (WebException) 169
168 {
169 cacheItems = null;
170 }
171 catch (InvalidOperationException)
172 {
173 cacheItems = null;
174 } */
175 catch (Exception) 170 catch (Exception)
176 { 171 {
177 // The service logs a sufficient error message. 172 // The service logs a sufficient error message.
178 } 173 }
179 174
180 175
181 if (savedcache != null) 176 if (savedcache != null)
182 existingitems = savedcache; 177 existingitems = savedcache;
183 } 178 }
184 } 179 }
180
185 // Existing items null means it's a fully new appearance 181 // Existing items null means it's a fully new appearance
186 if (existingitems == null) 182 if (existingitems == null)
187 { 183 {
188
189 for (int i = 0; i < maxCacheitemsLoop; i++) 184 for (int i = 0; i < maxCacheitemsLoop; i++)
190 { 185 {
191 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) 186 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
@@ -198,7 +193,7 @@ namespace OpenSim.Region.ClientStack.Linden
198 AppearanceManager.DEFAULT_AVATAR_TEXTURE; 193 AppearanceManager.DEFAULT_AVATAR_TEXTURE;
199 continue; 194 continue;
200 } 195 }
201 cacheItems[i].TextureID =face.TextureID; 196 cacheItems[i].TextureID = face.TextureID;
202 if (m_scene.AssetService != null) 197 if (m_scene.AssetService != null)
203 cacheItems[i].TextureAsset = 198 cacheItems[i].TextureAsset =
204 m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); 199 m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
@@ -207,15 +202,10 @@ namespace OpenSim.Region.ClientStack.Linden
207 { 202 {
208 m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length); 203 m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length);
209 } 204 }
210
211
212 } 205 }
213 } 206 }
214 else 207 else
215 208 {
216
217 {
218 // for each uploaded baked texture
219 for (int i = 0; i < maxCacheitemsLoop; i++) 209 for (int i = 0; i < maxCacheitemsLoop; i++)
220 { 210 {
221 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) 211 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
@@ -246,23 +236,24 @@ namespace OpenSim.Region.ClientStack.Linden
246 } 236 }
247 } 237 }
248 } 238 }
249
250
251
252 p.Appearance.WearableCacheItems = cacheItems; 239 p.Appearance.WearableCacheItems = cacheItems;
253
254
255 240
256 if (m_BakedTextureModule != null) 241 if (m_BakedTextureModule != null)
257 { 242 {
258 m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems); 243 m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems);
259 p.Appearance.WearableCacheItemsDirty = true; 244 p.Appearance.WearableCacheItemsDirty = true;
260 245
261 } 246 }
262 } 247 else
263 } 248 p.Appearance.WearableCacheItemsDirty = false;
264 }
265 249
250 for (int iter = 0; iter < maxCacheitemsLoop; iter++)
251 {
252 m_log.Debug("[CacheitemsLeaving] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" +
253 cacheItems[iter].TextureID);
254 }
255 }
256 */
266 public void PostInitialise() 257 public void PostInitialise()
267 { 258 {
268 } 259 }
@@ -280,23 +271,26 @@ namespace OpenSim.Region.ClientStack.Linden
280 271
281 public void RegisterCaps(UUID agentID, Caps caps) 272 public void RegisterCaps(UUID agentID, Caps caps)
282 { 273 {
283 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler( 274 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
284 caps, m_scene.AssetService, m_persistBakedTextures); 275 if (m_URL == "localhost")
276 {
277 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler(
278 caps, m_scene.AssetService, m_persistBakedTextures);
285 279
286 280 caps.RegisterHandler(
287
288 caps.RegisterHandler(
289 "UploadBakedTexture",
290 new RestStreamHandler(
291 "POST",
292 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
293 avatarhandler.UploadBakedTexture,
294 "UploadBakedTexture", 281 "UploadBakedTexture",
295 agentID.ToString())); 282 new RestStreamHandler(
296 283 "POST",
297 284 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
298 285 avatarhandler.UploadBakedTexture,
299 286 "UploadBakedTexture",
287 agentID.ToString()));
288
289 }
290 else
291 {
292 caps.RegisterHandler("UploadBakedTexture", m_URL);
293 }
300 } 294 }
301 } 295 }
302} 296}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 025ffea..1a19c1b 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -34,9 +34,7 @@ using log4net;
34using Nini.Config; 34using Nini.Config;
35using Mono.Addins; 35using Mono.Addins;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework; 37using OpenSim.Framework;
39using OpenSim.Framework.Monitoring;
40using OpenSim.Framework.Servers; 38using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
@@ -45,6 +43,9 @@ using OpenSim.Framework.Capabilities;
45using OpenSim.Services.Interfaces; 43using OpenSim.Services.Interfaces;
46using Caps = OpenSim.Framework.Capabilities.Caps; 44using Caps = OpenSim.Framework.Capabilities.Caps;
47using OpenSim.Capabilities.Handlers; 45using OpenSim.Capabilities.Handlers;
46using OpenSim.Framework.Monitoring;
47using OpenMetaverse;
48using OpenMetaverse.StructuredData;
48 49
49namespace OpenSim.Region.ClientStack.Linden 50namespace OpenSim.Region.ClientStack.Linden
50{ 51{
@@ -63,7 +64,7 @@ namespace OpenSim.Region.ClientStack.Linden
63 public List<UUID> folders; 64 public List<UUID> folders;
64 } 65 }
65 66
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
67 68
68 /// <summary> 69 /// <summary>
69 /// Control whether requests will be processed asynchronously. 70 /// Control whether requests will be processed asynchronously.
@@ -92,7 +93,7 @@ namespace OpenSim.Region.ClientStack.Linden
92 private bool m_Enabled; 93 private bool m_Enabled;
93 94
94 private string m_fetchInventoryDescendents2Url; 95 private string m_fetchInventoryDescendents2Url;
95 private string m_webFetchInventoryDescendentsUrl; 96// private string m_webFetchInventoryDescendentsUrl;
96 97
97 private static FetchInvDescHandler m_webFetchHandler; 98 private static FetchInvDescHandler m_webFetchHandler;
98 99
@@ -117,9 +118,10 @@ namespace OpenSim.Region.ClientStack.Linden
117 return; 118 return;
118 119
119 m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty); 120 m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty);
120 m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty); 121// m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty);
121 122
122 if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty) 123// if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty)
124 if (m_fetchInventoryDescendents2Url != string.Empty)
123 { 125 {
124 m_Enabled = true; 126 m_Enabled = true;
125 } 127 }
@@ -312,7 +314,8 @@ namespace OpenSim.Region.ClientStack.Linden
312 { 314 {
313 if (!reqinfo.folders.Contains(folderID)) 315 if (!reqinfo.folders.Contains(folderID))
314 { 316 {
315 //TODO: Port COF handling from Avination 317 if (sp.COF != UUID.Zero && sp.COF == folderID)
318 highPriority = true;
316 reqinfo.folders.Add(folderID); 319 reqinfo.folders.Add(folderID);
317 } 320 }
318 } 321 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index 4d0568d..15d6f7f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -234,6 +234,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 m_stopPacket = TexturePacketCount(); 234 m_stopPacket = TexturePacketCount();
235 } 235 }
236 236
237 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
238 if (m_stopPacket == 1 && m_layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
239
237 m_currentPacket = StartPacket; 240 m_currentPacket = StartPacket;
238 } 241 }
239 } 242 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index e7dd9d3..62206e9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -100,6 +100,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
100 public event AvatarPickerRequest OnAvatarPickerRequest; 100 public event AvatarPickerRequest OnAvatarPickerRequest;
101 public event StartAnim OnStartAnim; 101 public event StartAnim OnStartAnim;
102 public event StopAnim OnStopAnim; 102 public event StopAnim OnStopAnim;
103 public event ChangeAnim OnChangeAnim;
103 public event Action<IClientAPI> OnRequestAvatarsData; 104 public event Action<IClientAPI> OnRequestAvatarsData;
104 public event LinkObjects OnLinkObjects; 105 public event LinkObjects OnLinkObjects;
105 public event DelinkObjects OnDelinkObjects; 106 public event DelinkObjects OnDelinkObjects;
@@ -127,6 +128,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
127 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; 128 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
128 public event UpdatePrimFlags OnUpdatePrimFlags; 129 public event UpdatePrimFlags OnUpdatePrimFlags;
129 public event UpdatePrimTexture OnUpdatePrimTexture; 130 public event UpdatePrimTexture OnUpdatePrimTexture;
131 public event ClientChangeObject onClientChangeObject;
130 public event UpdateVector OnUpdatePrimGroupPosition; 132 public event UpdateVector OnUpdatePrimGroupPosition;
131 public event UpdateVector OnUpdatePrimSinglePosition; 133 public event UpdateVector OnUpdatePrimSinglePosition;
132 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 134 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -156,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
156 public event RequestTaskInventory OnRequestTaskInventory; 158 public event RequestTaskInventory OnRequestTaskInventory;
157 public event UpdateInventoryItem OnUpdateInventoryItem; 159 public event UpdateInventoryItem OnUpdateInventoryItem;
158 public event CopyInventoryItem OnCopyInventoryItem; 160 public event CopyInventoryItem OnCopyInventoryItem;
161 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
159 public event MoveInventoryItem OnMoveInventoryItem; 162 public event MoveInventoryItem OnMoveInventoryItem;
160 public event RemoveInventoryItem OnRemoveInventoryItem; 163 public event RemoveInventoryItem OnRemoveInventoryItem;
161 public event RemoveInventoryFolder OnRemoveInventoryFolder; 164 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -250,7 +253,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
250 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 253 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
251 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 254 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
252 public event ClassifiedDelete OnClassifiedDelete; 255 public event ClassifiedDelete OnClassifiedDelete;
253 public event ClassifiedDelete OnClassifiedGodDelete; 256 public event ClassifiedGodDelete OnClassifiedGodDelete;
254 public event EventNotificationAddRequest OnEventNotificationAddRequest; 257 public event EventNotificationAddRequest OnEventNotificationAddRequest;
255 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 258 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
256 public event EventGodDelete OnEventGodDelete; 259 public event EventGodDelete OnEventGodDelete;
@@ -281,10 +284,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
281 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 284 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
282 public event SimWideDeletesDelegate OnSimWideDeletes; 285 public event SimWideDeletesDelegate OnSimWideDeletes;
283 public event SendPostcard OnSendPostcard; 286 public event SendPostcard OnSendPostcard;
287 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
284 public event MuteListEntryUpdate OnUpdateMuteListEntry; 288 public event MuteListEntryUpdate OnUpdateMuteListEntry;
285 public event MuteListEntryRemove OnRemoveMuteListEntry; 289 public event MuteListEntryRemove OnRemoveMuteListEntry;
286 public event GodlikeMessage onGodlikeMessage; 290 public event GodlikeMessage onGodlikeMessage;
287 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 291 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
292 public event GenericCall2 OnUpdateThrottles;
288 293
289#pragma warning disable 0067 294#pragma warning disable 0067
290 public event GenericMessage OnGenericMessage; 295 public event GenericMessage OnGenericMessage;
@@ -333,7 +338,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 private PriorityQueue m_entityProps; 338 private PriorityQueue m_entityProps;
334 private Prioritizer m_prioritizer; 339 private Prioritizer m_prioritizer;
335 private bool m_disableFacelights = false; 340 private bool m_disableFacelights = false;
336 private volatile bool m_justEditedTerrain = false; 341
342 private bool m_VelocityInterpolate = false;
343 private const uint MaxTransferBytesPerPacket = 600;
344
337 /// <value> 345 /// <value>
338 /// List used in construction of data blocks for an object update packet. This is to stop us having to 346 /// List used in construction of data blocks for an object update packet. This is to stop us having to
339 /// continually recreate it. 347 /// continually recreate it.
@@ -345,14 +353,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
345 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 353 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
346 /// ownerless phantom. 354 /// ownerless phantom.
347 /// 355 ///
348 /// All manipulation of this set has to occur under a lock 356 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
349 /// 357 ///
350 /// </value> 358 /// </value>
351 protected HashSet<uint> m_killRecord; 359// protected HashSet<uint> m_killRecord;
352 360
353// protected HashSet<uint> m_attachmentsSent; 361// protected HashSet<uint> m_attachmentsSent;
354 362
355 private int m_animationSequenceNumber = 1; 363 private bool m_deliverPackets = true;
364
356 private bool m_SendLogoutPacketWhenClosing = true; 365 private bool m_SendLogoutPacketWhenClosing = true;
357 366
358 /// <summary> 367 /// <summary>
@@ -398,6 +407,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
398 get { return m_startpos; } 407 get { return m_startpos; }
399 set { m_startpos = value; } 408 set { m_startpos = value; }
400 } 409 }
410 public bool DeliverPackets
411 {
412 get { return m_deliverPackets; }
413 set {
414 m_deliverPackets = value;
415 m_udpClient.m_deliverPackets = value;
416 }
417 }
401 public UUID AgentId { get { return m_agentId; } } 418 public UUID AgentId { get { return m_agentId; } }
402 public ISceneAgent SceneAgent { get; set; } 419 public ISceneAgent SceneAgent { get; set; }
403 public UUID ActiveGroupId { get { return m_activeGroupID; } private set { m_activeGroupID = value; } } 420 public UUID ActiveGroupId { get { return m_activeGroupID; } private set { m_activeGroupID = value; } }
@@ -405,6 +422,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
405 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } private set { m_activeGroupPowers = value; } } 422 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } private set { m_activeGroupPowers = value; } }
406 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } 423 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
407 424
425 public int PingTimeMS
426 {
427 get
428 {
429 if (UDPClient != null)
430 return UDPClient.PingTimeMS;
431 return 0;
432 }
433 }
434
408 /// <summary> 435 /// <summary>
409 /// Entity update queues 436 /// Entity update queues
410 /// </summary> 437 /// </summary>
@@ -426,7 +453,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
426 public string Name { get { return FirstName + " " + LastName; } } 453 public string Name { get { return FirstName + " " + LastName; } }
427 454
428 public uint CircuitCode { get { return m_circuitCode; } } 455 public uint CircuitCode { get { return m_circuitCode; } }
429 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } 456 public int NextAnimationSequenceNumber
457 {
458 get { return m_udpServer.NextAnimationSequenceNumber; }
459 }
430 460
431 /// <summary> 461 /// <summary>
432 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to 462 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
@@ -447,7 +477,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
447 set { m_disableFacelights = value; } 477 set { m_disableFacelights = value; }
448 } 478 }
449 479
480 public List<uint> SelectedObjects {get; private set;}
481
450 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } 482 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
483
451 484
452 #endregion Properties 485 #endregion Properties
453 486
@@ -465,6 +498,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
465// DebugPacketLevel = 1; 498// DebugPacketLevel = 1;
466 499
467 CloseSyncLock = new Object(); 500 CloseSyncLock = new Object();
501 SelectedObjects = new List<uint>();
468 502
469 RegisterInterface<IClientIM>(this); 503 RegisterInterface<IClientIM>(this);
470 RegisterInterface<IClientInventory>(this); 504 RegisterInterface<IClientInventory>(this);
@@ -474,7 +508,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
474 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 508 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
475 m_entityProps = new PriorityQueue(m_scene.Entities.Count); 509 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
476 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 510 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
477 m_killRecord = new HashSet<uint>(); 511// m_killRecord = new HashSet<uint>();
478// m_attachmentsSent = new HashSet<uint>(); 512// m_attachmentsSent = new HashSet<uint>();
479 513
480 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 514 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
@@ -504,12 +538,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
504 538
505 #region Client Methods 539 #region Client Methods
506 540
541
542 /// <summary>
543 /// Close down the client view
544 /// </summary>
507 public void Close() 545 public void Close()
508 { 546 {
509 Close(false); 547 Close(true, false);
510 } 548 }
511 549
512 public void Close(bool force) 550 public void Close(bool sendStop, bool force)
513 { 551 {
514 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 552 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
515 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 553 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
@@ -526,7 +564,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
526 } 564 }
527 565
528 IsActive = false; 566 IsActive = false;
529 CloseWithoutChecks(); 567 CloseWithoutChecks(sendStop);
530 } 568 }
531 } 569 }
532 570
@@ -539,12 +577,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
539 /// 577 ///
540 /// Callers must lock ClosingSyncLock before calling. 578 /// Callers must lock ClosingSyncLock before calling.
541 /// </remarks> 579 /// </remarks>
542 public void CloseWithoutChecks() 580 public void CloseWithoutChecks(bool sendStop)
543 { 581 {
544 m_log.DebugFormat( 582 m_log.DebugFormat(
545 "[CLIENT]: Close has been called for {0} attached to scene {1}", 583 "[CLIENT]: Close has been called for {0} attached to scene {1}",
546 Name, m_scene.RegionInfo.RegionName); 584 Name, m_scene.RegionInfo.RegionName);
547 585
586 if (sendStop)
587 {
588 // Send the STOP packet
589 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
590 OutPacket(disable, ThrottleOutPacketType.Unknown);
591 }
592
548 // Shutdown the image manager 593 // Shutdown the image manager
549 ImageManager.Close(); 594 ImageManager.Close();
550 595
@@ -566,7 +611,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
566 611
567 // Disable UDP handling for this client 612 // Disable UDP handling for this client
568 m_udpClient.Shutdown(); 613 m_udpClient.Shutdown();
569 614
615
570 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 616 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
571 //GC.Collect(); 617 //GC.Collect();
572 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); 618 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
@@ -858,6 +904,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
858 904
859 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 905 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
860 { 906 {
907 m_thisAgentUpdateArgs.CameraAtAxis.X = float.MinValue;
908 m_thisAgentUpdateArgs.ControlFlags = uint.MaxValue;
909
861 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); 910 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
862 mov.SimData.ChannelVersion = m_channelVersion; 911 mov.SimData.ChannelVersion = m_channelVersion;
863 mov.AgentData.SessionID = m_sessionId; 912 mov.AgentData.SessionID = m_sessionId;
@@ -893,7 +942,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
893 reply.ChatData.OwnerID = ownerID; 942 reply.ChatData.OwnerID = ownerID;
894 reply.ChatData.SourceID = fromAgentID; 943 reply.ChatData.SourceID = fromAgentID;
895 944
896 OutPacket(reply, ThrottleOutPacketType.Task); 945 OutPacket(reply, ThrottleOutPacketType.Unknown);
897 } 946 }
898 947
899 /// <summary> 948 /// <summary>
@@ -926,32 +975,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
926 msg.MessageBlock.Message = Util.StringToBytes1024(im.message); 975 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
927 msg.MessageBlock.BinaryBucket = im.binaryBucket; 976 msg.MessageBlock.BinaryBucket = im.binaryBucket;
928 977
929 if (im.message.StartsWith("[grouptest]")) 978 OutPacket(msg, ThrottleOutPacketType.Task);
930 { // this block is test code for implementing group IM - delete when group IM is finished
931 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
932 if (eq != null)
933 {
934 im.dialog = 17;
935
936 //eq.ChatterboxInvitation(
937 // new UUID("00000000-68f9-1111-024e-222222111123"),
938 // "OpenSimulator Testing", im.fromAgentID, im.message, im.toAgentID, im.fromAgentName, im.dialog, 0,
939 // false, 0, new Vector3(), 1, im.imSessionID, im.fromGroup, im.binaryBucket);
940
941 eq.ChatterboxInvitation(
942 new UUID("00000000-68f9-1111-024e-222222111123"),
943 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
944 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
945
946 eq.ChatterBoxSessionAgentListUpdates(
947 new UUID("00000000-68f9-1111-024e-222222111123"),
948 new UUID(im.fromAgentID), new UUID(im.toAgentID), false, false, false);
949 }
950
951 Console.WriteLine("SendInstantMessage: " + msg);
952 }
953 else
954 OutPacket(msg, ThrottleOutPacketType.Task);
955 } 979 }
956 } 980 }
957 981
@@ -1182,6 +1206,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1182 OutPacket(GATRP, ThrottleOutPacketType.Task); 1206 OutPacket(GATRP, ThrottleOutPacketType.Task);
1183 } 1207 }
1184 1208
1209
1210 public virtual bool CanSendLayerData()
1211 {
1212 int n = m_udpClient.GetPacketsQueuedCount(ThrottleOutPacketType.Land);
1213 if ( n > 128)
1214 return false;
1215 return true;
1216 }
1217
1185 /// <summary> 1218 /// <summary>
1186 /// Send the region heightmap to the client 1219 /// Send the region heightmap to the client
1187 /// This method is only called when not doing intellegent terrain patch sending and 1220 /// This method is only called when not doing intellegent terrain patch sending and
@@ -1192,6 +1225,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1192 public virtual void SendLayerData(float[] map) 1225 public virtual void SendLayerData(float[] map)
1193 { 1226 {
1194 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData(), "LLClientView.DoSendLayerData"); 1227 Util.FireAndForget(DoSendLayerData, m_scene.Heightmap.GetTerrainData(), "LLClientView.DoSendLayerData");
1228
1229 // Send it sync, and async. It's not that much data
1230 // and it improves user experience just so much!
1231// DoSendLayerData(map);
1195 } 1232 }
1196 1233
1197 /// <summary> 1234 /// <summary>
@@ -1214,7 +1251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1214 //} 1251 //}
1215 1252
1216 // Send LayerData in a spiral pattern. Fun! 1253 // Send LayerData in a spiral pattern. Fun!
1217 SendLayerTopRight(map, 0, 0, map.SizeX/Constants.TerrainPatchSize-1, map.SizeY/Constants.TerrainPatchSize-1); 1254 SendLayerTopRight(map, 0, 0, map.SizeX / Constants.TerrainPatchSize - 1, map.SizeY / Constants.TerrainPatchSize - 1);
1218 } 1255 }
1219 catch (Exception e) 1256 catch (Exception e)
1220 { 1257 {
@@ -1250,23 +1287,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1250 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1); 1287 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1251 } 1288 }
1252 1289
1253 /// <summary>
1254 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1255 /// </summary>
1256 /// <param name="map">heightmap</param>
1257 /// <param name="px">X coordinate for patches 0..12</param>
1258 /// <param name="py">Y coordinate for patches 0..15</param>
1259 // private void SendLayerPacket(float[] map, int y, int x)
1260 // {
1261 // int[] patches = new int[4];
1262 // patches[0] = x + 0 + y * 16;
1263 // patches[1] = x + 1 + y * 16;
1264 // patches[2] = x + 2 + y * 16;
1265 // patches[3] = x + 3 + y * 16;
1266
1267 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
1268 // OutPacket(layerpack, ThrottleOutPacketType.Land);
1269 // }
1270 1290
1271 // Legacy form of invocation that passes around a bare data array. 1291 // Legacy form of invocation that passes around a bare data array.
1272 // Just ignore what was passed and use the real terrain info that is part of the scene. 1292 // Just ignore what was passed and use the real terrain info that is part of the scene.
@@ -1316,6 +1336,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1316 } 1336 }
1317 1337
1318 /// <summary> 1338 /// <summary>
1339
1319 /// Sends a terrain packet for the point specified. 1340 /// Sends a terrain packet for the point specified.
1320 /// This is a legacy call that has refarbed the terrain into a flat map of floats. 1341 /// This is a legacy call that has refarbed the terrain into a flat map of floats.
1321 /// We just use the terrain from the region we know about. 1342 /// We just use the terrain from the region we know about.
@@ -1334,32 +1355,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1334 { 1355 {
1335 try 1356 try
1336 { 1357 {
1337 /* test code using the terrain compressor in libOpenMetaverse 1358 byte landPacketType;
1338 int[] patchInd = new int[1]; 1359 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
1339 patchInd[0] = px + (py * Constants.TerrainPatchSize); 1360 landPacketType = (byte)TerrainPatch.LayerType.LandExtended;
1340 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(terrData.GetFloatsSerialized(), patchInd); 1361 else
1341 */ 1362 landPacketType = (byte)TerrainPatch.LayerType.Land;
1342 // Many, many patches could have been passed to us. Since the patches will be compressed
1343 // into variable sized blocks, we cannot pre-compute how many will fit into one
1344 // packet. While some fancy packing algorithm is possible, 4 seems to always fit.
1345 int PatchesAssumedToFit = 4;
1346 for (int pcnt = 0; pcnt < px.Length; pcnt += PatchesAssumedToFit)
1347 {
1348 int remaining = Math.Min(px.Length - pcnt, PatchesAssumedToFit);
1349 int[] xPatches = new int[remaining];
1350 int[] yPatches = new int[remaining];
1351 for (int ii = 0; ii < remaining; ii++)
1352 {
1353 xPatches[ii] = px[pcnt + ii];
1354 yPatches[ii] = py[pcnt + ii];
1355 }
1356 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, xPatches, yPatches);
1357 // DebugSendingPatches("SendLayerDataInternal", xPatches, yPatches);
1358
1359 SendTheLayerPacket(layerpack);
1360 }
1361 // LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLandPacket(terrData, px, py);
1362 1363
1364 List<LayerDataPacket> packets = OpenSimTerrainCompressor.CreateLayerDataPackets(terrData, px, py, landPacketType);
1365 foreach(LayerDataPacket pkt in packets)
1366 OutPacket(pkt, ThrottleOutPacketType.Land);
1363 } 1367 }
1364 catch (Exception e) 1368 catch (Exception e)
1365 { 1369 {
@@ -1367,36 +1371,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1367 } 1371 }
1368 } 1372 }
1369 1373
1370 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a
1371 // sub optimal editing experience. To alleviate this issue, when the user edits the terrain, we
1372 // start skipping the queues until they're done editing the terrain. We also make them
1373 // unreliable because it's extremely likely that multiple packets will be sent for a terrain patch
1374 // area invalidating previous packets for that area.
1375
1376 // It's possible for an editing user to flood themselves with edited packets but the majority
1377 // of use cases are such that only a tiny percentage of users will be editing the terrain.
1378 // Other, non-editing users will see the edits much slower.
1379
1380 // One last note on this topic, by the time users are going to be editing the terrain, it's
1381 // extremely likely that the sim will have rezzed already and therefore this is not likely going
1382 // to cause any additional issues with lost packets, objects or terrain patches.
1383
1384 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we
1385 // only have one cache miss.
1386 private void SendTheLayerPacket(LayerDataPacket layerpack)
1387 {
1388 if (m_justEditedTerrain)
1389 {
1390 layerpack.Header.Reliable = false;
1391 OutPacket(layerpack, ThrottleOutPacketType.Unknown );
1392 }
1393 else
1394 {
1395 layerpack.Header.Reliable = true;
1396 OutPacket(layerpack, ThrottleOutPacketType.Land);
1397 }
1398 }
1399
1400 /// <summary> 1374 /// <summary>
1401 /// Send the wind matrix to the client 1375 /// Send the wind matrix to the client
1402 /// </summary> 1376 /// </summary>
@@ -1432,13 +1406,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1432 patches[1].Data[x] = windSpeeds[x].Y; 1406 patches[1].Data[x] = windSpeeds[x].Y;
1433 } 1407 }
1434 1408
1409 // neither we or viewers have extended wind
1435 byte layerType = (byte)TerrainPatch.LayerType.Wind; 1410 byte layerType = (byte)TerrainPatch.LayerType.Wind;
1436 if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
1437 layerType = (byte)TerrainPatch.LayerType.WindExtended;
1438 1411
1439 // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType); 1412 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacketStandardSize(patches, layerType);
1440 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
1441 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
1442 layerpack.Header.Zerocoded = true; 1413 layerpack.Header.Zerocoded = true;
1443 OutPacket(layerpack, ThrottleOutPacketType.Wind); 1414 OutPacket(layerpack, ThrottleOutPacketType.Wind);
1444 } 1415 }
@@ -1461,14 +1432,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1461 patches[0].Data[y * 16 + x] = cloudCover[y * 16 + x]; 1432 patches[0].Data[y * 16 + x] = cloudCover[y * 16 + x];
1462 } 1433 }
1463 } 1434 }
1464 1435 // neither we or viewers have extended clouds
1465 byte layerType = (byte)TerrainPatch.LayerType.Cloud; 1436 byte layerType = (byte)TerrainPatch.LayerType.Cloud;
1466 if (m_scene.RegionInfo.RegionSizeX > Constants.RegionSize || m_scene.RegionInfo.RegionSizeY > Constants.RegionSize)
1467 layerType = (byte)TerrainPatch.LayerType.CloudExtended;
1468 1437
1469 // LayerDataPacket layerpack = TerrainCompressor.CreateLayerDataPacket(patches, (TerrainPatch.LayerType)layerType); 1438 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacketStandardSize(patches, layerType);
1470 LayerDataPacket layerpack = OpenSimTerrainCompressor.CreateLayerDataPacket(patches, layerType,
1471 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY);
1472 layerpack.Header.Zerocoded = true; 1439 layerpack.Header.Zerocoded = true;
1473 OutPacket(layerpack, ThrottleOutPacketType.Cloud); 1440 OutPacket(layerpack, ThrottleOutPacketType.Cloud);
1474 } 1441 }
@@ -1735,11 +1702,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1735 pc.PingID.OldestUnacked = 0; 1702 pc.PingID.OldestUnacked = 0;
1736 1703
1737 OutPacket(pc, ThrottleOutPacketType.Unknown); 1704 OutPacket(pc, ThrottleOutPacketType.Unknown);
1705 UDPClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1738 } 1706 }
1739 1707
1740 public void SendKillObject(List<uint> localIDs) 1708 public void SendKillObject(List<uint> localIDs)
1741 { 1709 {
1742// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1710 // think we do need this
1711 // foreach (uint id in localIDs)
1712 // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1713
1714 // remove pending entities
1715 lock (m_entityProps.SyncRoot)
1716 m_entityProps.Remove(localIDs);
1717 lock (m_entityUpdates.SyncRoot)
1718 m_entityUpdates.Remove(localIDs);
1743 1719
1744 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1720 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1745 // TODO: don't create new blocks if recycling an old packet 1721 // TODO: don't create new blocks if recycling an old packet
@@ -1752,28 +1728,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1752 kill.Header.Reliable = true; 1728 kill.Header.Reliable = true;
1753 kill.Header.Zerocoded = true; 1729 kill.Header.Zerocoded = true;
1754 1730
1755 if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) 1731 OutPacket(kill, ThrottleOutPacketType.Task);
1756 { 1732 }
1757 OutPacket(kill, ThrottleOutPacketType.Task);
1758 }
1759 else
1760 {
1761 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1762 // condition where a kill can be processed before an out-of-date update for the same object.
1763 // ProcessEntityUpdates() also takes the m_killRecord lock.
1764 lock (m_killRecord)
1765 {
1766 foreach (uint localID in localIDs)
1767 m_killRecord.Add(localID);
1768
1769 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1770 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1771 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1772 // scene objects in a viewer until that viewer is relogged in.
1773 OutPacket(kill, ThrottleOutPacketType.Task);
1774 }
1775 }
1776 }
1777 1733
1778 /// <summary> 1734 /// <summary>
1779 /// Send information about the items contained in a folder to the client. 1735 /// Send information about the items contained in a folder to the client.
@@ -1895,7 +1851,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1895 newBlock.CreationDate = item.CreationDate; 1851 newBlock.CreationDate = item.CreationDate;
1896 newBlock.SalePrice = item.SalePrice; 1852 newBlock.SalePrice = item.SalePrice;
1897 newBlock.SaleType = item.SaleType; 1853 newBlock.SaleType = item.SaleType;
1898 newBlock.Flags = item.Flags; 1854 newBlock.Flags = item.Flags & 0x2000ff;
1899 1855
1900 newBlock.CRC = 1856 newBlock.CRC =
1901 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType, 1857 Helpers.InventoryCRC(newBlock.CreationDate, newBlock.SaleType,
@@ -2151,7 +2107,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2151 itemBlock.GroupID = item.GroupID; 2107 itemBlock.GroupID = item.GroupID;
2152 itemBlock.GroupOwned = item.GroupOwned; 2108 itemBlock.GroupOwned = item.GroupOwned;
2153 itemBlock.GroupMask = item.GroupPermissions; 2109 itemBlock.GroupMask = item.GroupPermissions;
2154 itemBlock.Flags = item.Flags; 2110 itemBlock.Flags = item.Flags & 0x2000ff;
2155 itemBlock.SalePrice = item.SalePrice; 2111 itemBlock.SalePrice = item.SalePrice;
2156 itemBlock.SaleType = item.SaleType; 2112 itemBlock.SaleType = item.SaleType;
2157 itemBlock.CreationDate = item.CreationDate; 2113 itemBlock.CreationDate = item.CreationDate;
@@ -2218,7 +2174,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2218 bulkUpdate.ItemData[0].GroupID = item.GroupID; 2174 bulkUpdate.ItemData[0].GroupID = item.GroupID;
2219 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned; 2175 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned;
2220 bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions; 2176 bulkUpdate.ItemData[0].GroupMask = item.GroupPermissions;
2221 bulkUpdate.ItemData[0].Flags = item.Flags; 2177 bulkUpdate.ItemData[0].Flags = item.Flags & 0x2000ff;
2222 bulkUpdate.ItemData[0].SalePrice = item.SalePrice; 2178 bulkUpdate.ItemData[0].SalePrice = item.SalePrice;
2223 bulkUpdate.ItemData[0].SaleType = item.SaleType; 2179 bulkUpdate.ItemData[0].SaleType = item.SaleType;
2224 2180
@@ -2234,9 +2190,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2234 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 2190 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2235 } 2191 }
2236 2192
2237 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2238 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 2193 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2239 { 2194 {
2195 SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
2196 }
2197
2198 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2199 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
2200 {
2240 const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff; 2201 const uint FULL_MASK_PERMISSIONS = (uint)0x7fffffff;
2241 2202
2242 UpdateCreateInventoryItemPacket InventoryReply 2203 UpdateCreateInventoryItemPacket InventoryReply
@@ -2246,6 +2207,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2246 // TODO: don't create new blocks if recycling an old packet 2207 // TODO: don't create new blocks if recycling an old packet
2247 InventoryReply.AgentData.AgentID = AgentId; 2208 InventoryReply.AgentData.AgentID = AgentId;
2248 InventoryReply.AgentData.SimApproved = true; 2209 InventoryReply.AgentData.SimApproved = true;
2210 InventoryReply.AgentData.TransactionID = transactionID;
2249 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; 2211 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2250 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); 2212 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2251 InventoryReply.InventoryData[0].ItemID = Item.ID; 2213 InventoryReply.InventoryData[0].ItemID = Item.ID;
@@ -2266,7 +2228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2266 InventoryReply.InventoryData[0].GroupID = Item.GroupID; 2228 InventoryReply.InventoryData[0].GroupID = Item.GroupID;
2267 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned; 2229 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned;
2268 InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions; 2230 InventoryReply.InventoryData[0].GroupMask = Item.GroupPermissions;
2269 InventoryReply.InventoryData[0].Flags = Item.Flags; 2231 InventoryReply.InventoryData[0].Flags = Item.Flags & 0x2000ff;
2270 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice; 2232 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice;
2271 InventoryReply.InventoryData[0].SaleType = Item.SaleType; 2233 InventoryReply.InventoryData[0].SaleType = Item.SaleType;
2272 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate; 2234 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate;
@@ -2315,16 +2277,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2315 replytask.InventoryData.TaskID = taskID; 2277 replytask.InventoryData.TaskID = taskID;
2316 replytask.InventoryData.Serial = serial; 2278 replytask.InventoryData.Serial = serial;
2317 replytask.InventoryData.Filename = fileName; 2279 replytask.InventoryData.Filename = fileName;
2318 OutPacket(replytask, ThrottleOutPacketType.Asset); 2280 OutPacket(replytask, ThrottleOutPacketType.Task);
2319 } 2281 }
2320 2282
2321 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 2283 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
2322 { 2284 {
2285 ThrottleOutPacketType type = ThrottleOutPacketType.Asset;
2286 if (isTaskInventory)
2287 type = ThrottleOutPacketType.Task;
2288
2323 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); 2289 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2324 sendXfer.XferID.ID = xferID; 2290 sendXfer.XferID.ID = xferID;
2325 sendXfer.XferID.Packet = packet; 2291 sendXfer.XferID.Packet = packet;
2326 sendXfer.DataPacket.Data = data; 2292 sendXfer.DataPacket.Data = data;
2327 OutPacket(sendXfer, ThrottleOutPacketType.Asset); 2293 OutPacket(sendXfer, type);
2328 } 2294 }
2329 2295
2330 public void SendAbortXferPacket(ulong xferID) 2296 public void SendAbortXferPacket(ulong xferID)
@@ -2471,14 +2437,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2471 // this is the username of the *owner* 2437 // this is the username of the *owner*
2472 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName); 2438 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
2473 dialog.Data.LastName = Util.StringToBytes256(ownerLastName); 2439 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
2474 dialog.Data.Message = Util.StringToBytes1024(msg); 2440 dialog.Data.Message = Util.StringToBytes(msg,512);
2475 dialog.Data.ImageID = textureID; 2441 dialog.Data.ImageID = textureID;
2476 dialog.Data.ChatChannel = ch; 2442 dialog.Data.ChatChannel = ch;
2477 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length]; 2443 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
2478 for (int i = 0; i < buttonlabels.Length; i++) 2444 for (int i = 0; i < buttonlabels.Length; i++)
2479 { 2445 {
2480 buttons[i] = new ScriptDialogPacket.ButtonsBlock(); 2446 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
2481 buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]); 2447 buttons[i].ButtonLabel = Util.StringToBytes(buttonlabels[i],24);
2482 } 2448 }
2483 dialog.Buttons = buttons; 2449 dialog.Buttons = buttons;
2484 2450
@@ -2514,6 +2480,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2514 OutPacket(sound, ThrottleOutPacketType.Task); 2480 OutPacket(sound, ThrottleOutPacketType.Task);
2515 } 2481 }
2516 2482
2483 public void SendTransferAbort(TransferRequestPacket transferRequest)
2484 {
2485 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2486 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2487 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2488 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2489 OutPacket(abort, ThrottleOutPacketType.Task);
2490 }
2491
2517 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2492 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2518 { 2493 {
2519 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2494 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2730,8 +2705,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2730 OutPacket(offp, ThrottleOutPacketType.Task); 2705 OutPacket(offp, ThrottleOutPacketType.Task);
2731 } 2706 }
2732 2707
2733 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, 2708 public void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY)
2734 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) 2709 {
2710 FindAgentPacket fap = new FindAgentPacket();
2711 fap.AgentBlock.Hunter = HunterID;
2712 fap.AgentBlock.Prey = PreyID;
2713 fap.AgentBlock.SpaceIP = 0;
2714
2715 fap.LocationBlock = new FindAgentPacket.LocationBlockBlock[1];
2716 fap.LocationBlock[0] = new FindAgentPacket.LocationBlockBlock();
2717 fap.LocationBlock[0].GlobalX = GlobalX;
2718 fap.LocationBlock[0].GlobalY = GlobalY;
2719
2720 OutPacket(fap, ThrottleOutPacketType.Task);
2721 }
2722
2723 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos,
2724 Quaternion SitOrientation, bool autopilot,
2725 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
2735 { 2726 {
2736 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); 2727 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2737 avatarSitResponse.SitObject.ID = TargetID; 2728 avatarSitResponse.SitObject.ID = TargetID;
@@ -2819,6 +2810,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2819 float friction = part.Friction; 2810 float friction = part.Friction;
2820 float bounce = part.Restitution; 2811 float bounce = part.Restitution;
2821 float gravmod = part.GravityModifier; 2812 float gravmod = part.GravityModifier;
2813
2822 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId); 2814 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
2823 } 2815 }
2824 } 2816 }
@@ -2889,8 +2881,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2889 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType); 2881 LogHeader, req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2890 return; 2882 return;
2891 } 2883 }
2884 int WearableOut = 0;
2885 bool isWearable = false;
2886
2887 if (req.AssetInf != null)
2888 isWearable =
2889 ((AssetType) req.AssetInf.Type ==
2890 AssetType.Bodypart || (AssetType) req.AssetInf.Type == AssetType.Clothing);
2892 2891
2893 //m_log.Debug("sending asset " + req.RequestAssetID); 2892
2893 //m_log.Debug("sending asset " + req.RequestAssetID + ", iswearable: " + isWearable);
2894
2895
2896 //if (isWearable)
2897 // m_log.Debug((AssetType)req.AssetInf.Type);
2898
2894 TransferInfoPacket Transfer = new TransferInfoPacket(); 2899 TransferInfoPacket Transfer = new TransferInfoPacket();
2895 Transfer.TransferInfo.ChannelType = 2; 2900 Transfer.TransferInfo.ChannelType = 2;
2896 Transfer.TransferInfo.Status = 0; 2901 Transfer.TransferInfo.Status = 0;
@@ -2912,7 +2917,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2912 Transfer.TransferInfo.Size = req.AssetInf.Data.Length; 2917 Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
2913 Transfer.TransferInfo.TransferID = req.TransferRequestID; 2918 Transfer.TransferInfo.TransferID = req.TransferRequestID;
2914 Transfer.Header.Zerocoded = true; 2919 Transfer.Header.Zerocoded = true;
2915 OutPacket(Transfer, ThrottleOutPacketType.Asset); 2920 OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2916 2921
2917 if (req.NumPackets == 1) 2922 if (req.NumPackets == 1)
2918 { 2923 {
@@ -2923,12 +2928,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2923 TransferPacket.TransferData.Data = req.AssetInf.Data; 2928 TransferPacket.TransferData.Data = req.AssetInf.Data;
2924 TransferPacket.TransferData.Status = 1; 2929 TransferPacket.TransferData.Status = 1;
2925 TransferPacket.Header.Zerocoded = true; 2930 TransferPacket.Header.Zerocoded = true;
2926 OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 2931 OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2927 } 2932 }
2928 else 2933 else
2929 { 2934 {
2930 int processedLength = 0; 2935 int processedLength = 0;
2931 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; 2936// int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2937
2938 int maxChunkSize = (int) MaxTransferBytesPerPacket;
2932 int packetNumber = 0; 2939 int packetNumber = 0;
2933 2940
2934 while (processedLength < req.AssetInf.Data.Length) 2941 while (processedLength < req.AssetInf.Data.Length)
@@ -2954,7 +2961,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2954 TransferPacket.TransferData.Status = 1; 2961 TransferPacket.TransferData.Status = 1;
2955 } 2962 }
2956 TransferPacket.Header.Zerocoded = true; 2963 TransferPacket.Header.Zerocoded = true;
2957 OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 2964 OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2958 2965
2959 processedLength += chunkSize; 2966 processedLength += chunkSize;
2960 packetNumber++; 2967 packetNumber++;
@@ -2999,7 +3006,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2999 reply.Data.ParcelID = parcelID; 3006 reply.Data.ParcelID = parcelID;
3000 reply.Data.OwnerID = land.OwnerID; 3007 reply.Data.OwnerID = land.OwnerID;
3001 reply.Data.Name = Utils.StringToBytes(land.Name); 3008 reply.Data.Name = Utils.StringToBytes(land.Name);
3002 reply.Data.Desc = Utils.StringToBytes(land.Description); 3009 if (land != null && land.Description != null && land.Description != String.Empty)
3010 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
3011 else
3012 reply.Data.Desc = new Byte[0];
3003 reply.Data.ActualArea = land.Area; 3013 reply.Data.ActualArea = land.Area;
3004 reply.Data.BillableArea = land.Area; // TODO: what is this? 3014 reply.Data.BillableArea = land.Area; // TODO: what is this?
3005 3015
@@ -3385,7 +3395,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3385 AgentData.Add(AgentDataMap); 3395 AgentData.Add(AgentDataMap);
3386 llsd.Add("AgentData", AgentData); 3396 llsd.Add("AgentData", AgentData);
3387 OSDArray GroupData = new OSDArray(data.Length); 3397 OSDArray GroupData = new OSDArray(data.Length);
3388 OSDArray NewGroupData = new OSDArray(data.Length); 3398// OSDArray NewGroupData = new OSDArray(data.Length);
3389 foreach (GroupMembershipData m in data) 3399 foreach (GroupMembershipData m in data)
3390 { 3400 {
3391 OSDMap GroupDataMap = new OSDMap(6); 3401 OSDMap GroupDataMap = new OSDMap(6);
@@ -3396,12 +3406,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3396 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID)); 3406 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID));
3397 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName)); 3407 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName));
3398 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture)); 3408 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture));
3399 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile)); 3409// NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile));
3400 GroupData.Add(GroupDataMap); 3410 GroupData.Add(GroupDataMap);
3401 NewGroupData.Add(NewGroupDataMap); 3411// NewGroupData.Add(NewGroupDataMap);
3402 } 3412 }
3403 llsd.Add("GroupData", GroupData); 3413 llsd.Add("GroupData", GroupData);
3404 llsd.Add("NewGroupData", NewGroupData); 3414 // llsd.Add("NewGroupData", NewGroupData);
3405 3415
3406 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>(); 3416 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>();
3407 if (eq != null) 3417 if (eq != null)
@@ -3410,6 +3420,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3410 } 3420 }
3411 } 3421 }
3412 3422
3423 public void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data)
3424 {
3425 IEventQueue eq = this.Scene.RequestModuleInterface<IEventQueue>();
3426
3427 // use UDP if no caps
3428 if (eq == null)
3429 {
3430 SendGroupMembership(data);
3431 }
3432
3433 OSDMap llsd = new OSDMap(3);
3434 OSDArray AgentData = new OSDArray(1);
3435 OSDMap AgentDataMap = new OSDMap(1);
3436 AgentDataMap.Add("AgentID", OSD.FromUUID(this.AgentId));
3437 AgentDataMap.Add("AvatarID", OSD.FromUUID(avatarID));
3438 AgentData.Add(AgentDataMap);
3439 llsd.Add("AgentData", AgentData);
3440 OSDArray GroupData = new OSDArray(data.Length);
3441 OSDArray NewGroupData = new OSDArray(data.Length);
3442 foreach (GroupMembershipData m in data)
3443 {
3444 OSDMap GroupDataMap = new OSDMap(6);
3445 OSDMap NewGroupDataMap = new OSDMap(1);
3446 GroupDataMap.Add("GroupPowers", OSD.FromULong(m.GroupPowers));
3447 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(m.AcceptNotices));
3448 GroupDataMap.Add("GroupTitle", OSD.FromString(m.GroupTitle));
3449 GroupDataMap.Add("GroupID", OSD.FromUUID(m.GroupID));
3450 GroupDataMap.Add("GroupName", OSD.FromString(m.GroupName));
3451 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(m.GroupPicture));
3452 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(m.ListInProfile));
3453 GroupData.Add(GroupDataMap);
3454 NewGroupData.Add(NewGroupDataMap);
3455 }
3456 llsd.Add("GroupData", GroupData);
3457 llsd.Add("NewGroupData", NewGroupData);
3458
3459 eq.Enqueue(BuildEvent("AgentGroupDataUpdate", llsd), this.AgentId);
3460 }
3461
3413 public void SendJoinGroupReply(UUID groupID, bool success) 3462 public void SendJoinGroupReply(UUID groupID, bool success)
3414 { 3463 {
3415 JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply); 3464 JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply);
@@ -3706,24 +3755,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3706 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count]; 3755 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count];
3707 AgentWearablesUpdatePacket.WearableDataBlock awb; 3756 AgentWearablesUpdatePacket.WearableDataBlock awb;
3708 int idx = 0; 3757 int idx = 0;
3709 for (int i = 0; i < wearables.Length; i++) 3758
3710 { 3759 for (int i = 0; i < wearables.Length; i++)
3711 for (int j = 0; j < wearables[i].Count; j++) 3760 {
3712 { 3761 for (int j = 0; j < wearables[i].Count; j++)
3713 awb = new AgentWearablesUpdatePacket.WearableDataBlock(); 3762 {
3714 awb.WearableType = (byte)i; 3763 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
3715 awb.AssetID = wearables[i][j].AssetID; 3764 awb.WearableType = (byte) i;
3716 awb.ItemID = wearables[i][j].ItemID; 3765 awb.AssetID = wearables[i][j].AssetID;
3717 aw.WearableData[idx] = awb; 3766 awb.ItemID = wearables[i][j].ItemID;
3718 idx++; 3767 aw.WearableData[idx] = awb;
3719 3768 idx++;
3720// m_log.DebugFormat( 3769
3721// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", 3770 // m_log.DebugFormat(
3722// awb.ItemID, awb.AssetID, i, Name); 3771 // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
3723 } 3772 // awb.ItemID, awb.AssetID, i, Name);
3724 } 3773 }
3774 }
3725 3775
3726 OutPacket(aw, ThrottleOutPacketType.Task); 3776 OutPacket(aw, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3727 } 3777 }
3728 3778
3729 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) 3779 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
@@ -3749,8 +3799,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3749 avp.Sender.ID = agentID; 3799 avp.Sender.ID = agentID;
3750 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; 3800 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0];
3751 avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0]; 3801 avp.AppearanceHover = new AvatarAppearancePacket.AppearanceHoverBlock[0];
3802
3803// this need be use in future ?
3804// avp.AppearanceData[0].AppearanceVersion = 0;
3805// avp.AppearanceData[0].CofVersion = 0;
3806
3752 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); 3807 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3753 OutPacket(avp, ThrottleOutPacketType.Task); 3808 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3754 } 3809 }
3755 3810
3756 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3811 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3778,7 +3833,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3778 ani.AnimationSourceList[i].ObjectID = objectIDs[i]; 3833 ani.AnimationSourceList[i].ObjectID = objectIDs[i];
3779 } 3834 }
3780 ani.Header.Reliable = false; 3835 ani.Header.Reliable = false;
3781 OutPacket(ani, ThrottleOutPacketType.Task); 3836 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3782 } 3837 }
3783 3838
3784 #endregion 3839 #endregion
@@ -3802,12 +3857,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3802 objupdate.Header.Zerocoded = true; 3857 objupdate.Header.Zerocoded = true;
3803 3858
3804 objupdate.RegionData.RegionHandle = presence.RegionHandle; 3859 objupdate.RegionData.RegionHandle = presence.RegionHandle;
3805 objupdate.RegionData.TimeDilation = ushort.MaxValue; 3860// objupdate.RegionData.TimeDilation = ushort.MaxValue;
3806 3861 objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
3807 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 3862 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3808 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); 3863 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
3809 3864
3810 OutPacket(objupdate, ThrottleOutPacketType.Task); 3865 OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3811 3866
3812 // We need to record the avatar local id since the root prim of an attachment points to this. 3867 // We need to record the avatar local id since the root prim of an attachment points to this.
3813// m_attachmentsSent.Add(avatar.LocalId); 3868// m_attachmentsSent.Add(avatar.LocalId);
@@ -3866,6 +3921,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3866 /// </summary> 3921 /// </summary>
3867 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3922 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3868 { 3923 {
3924/*
3869 if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3925 if (entity.UUID == m_agentId && !updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3870 { 3926 {
3871 ImprovedTerseObjectUpdatePacket packet 3927 ImprovedTerseObjectUpdatePacket packet
@@ -3876,15 +3932,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3876 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 3932 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
3877 packet.ObjectData[0] = CreateImprovedTerseBlock(entity, false); 3933 packet.ObjectData[0] = CreateImprovedTerseBlock(entity, false);
3878 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 3934 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3935 return;
3879 } 3936 }
3880 else 3937*/
3938 if (entity is SceneObjectPart)
3881 { 3939 {
3882 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3940 SceneObjectPart e = (SceneObjectPart)entity;
3883 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3941 SceneObjectGroup g = e.ParentGroup;
3884 3942 if (g.HasPrivateAttachmentPoint && g.OwnerID != AgentId)
3885 lock (m_entityUpdates.SyncRoot) 3943 return; // Don't send updates for other people's HUDs
3886 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3887 } 3944 }
3945
3946 //double priority = m_prioritizer.GetUpdatePriority(this, entity);
3947 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3948
3949 lock (m_entityUpdates.SyncRoot)
3950 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3888 } 3951 }
3889 3952
3890 /// <summary> 3953 /// <summary>
@@ -3894,8 +3957,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3894 /// The original update time is used for the merged update. 3957 /// The original update time is used for the merged update.
3895 /// </summary> 3958 /// </summary>
3896 private void ResendPrimUpdate(EntityUpdate update) 3959 private void ResendPrimUpdate(EntityUpdate update)
3897 { 3960 {
3898 // If the update exists in priority queue, it will be updated. 3961 // If the update exists in priority queue, it will be updated.
3899 // If it does not exist then it will be added with the current (rather than its original) priority 3962 // If it does not exist then it will be added with the current (rather than its original) priority
3900 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); 3963 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
3901 3964
@@ -3919,7 +3982,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3919 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); 3982 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
3920 3983
3921 // Count this as a resent packet since we are going to requeue all of the updates contained in it 3984 // Count this as a resent packet since we are going to requeue all of the updates contained in it
3922 Interlocked.Increment(ref m_udpClient.PacketsResent); 3985 Interlocked.Increment(ref m_udpClient.PacketsResent);
3923 3986
3924 // We're not going to worry about interlock yet since its not currently critical that this total count 3987 // We're not going to worry about interlock yet since its not currently critical that this total count
3925 // is 100% correct 3988 // is 100% correct
@@ -3928,18 +3991,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3928 foreach (EntityUpdate update in updates) 3991 foreach (EntityUpdate update in updates)
3929 ResendPrimUpdate(update); 3992 ResendPrimUpdate(update);
3930 } 3993 }
3931 3994
3932// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3933// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3934// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3935// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3936//
3937// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3938// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3939// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3940// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3941
3942
3943 private void ProcessEntityUpdates(int maxUpdates) 3995 private void ProcessEntityUpdates(int maxUpdates)
3944 { 3996 {
3945 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3997 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3952,15 +4004,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3952 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 4004 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3953 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 4005 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3954 4006
3955// objectUpdateBlocks.Value.Clear();
3956// compressedUpdateBlocks.Value.Clear();
3957// terseUpdateBlocks.Value.Clear();
3958// terseAgentUpdateBlocks.Value.Clear();
3959// objectUpdates.Value.Clear();
3960// compressedUpdates.Value.Clear();
3961// terseUpdates.Value.Clear();
3962// terseAgentUpdates.Value.Clear();
3963
3964 // Check to see if this is a flush 4007 // Check to see if this is a flush
3965 if (maxUpdates <= 0) 4008 if (maxUpdates <= 0)
3966 { 4009 {
@@ -3971,54 +4014,71 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3971 4014
3972 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 4015 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3973 // condition where a kill can be processed before an out-of-date update for the same object. 4016 // condition where a kill can be processed before an out-of-date update for the same object.
3974 lock (m_killRecord) 4017// float avgTimeDilation = 0.0f;
4018 IEntityUpdate iupdate;
4019 Int32 timeinqueue; // this is just debugging code & can be dropped later
4020
4021 while (updatesThisCall < maxUpdates)
3975 { 4022 {
3976 float avgTimeDilation = 1.0f; 4023 lock (m_entityUpdates.SyncRoot)
3977 IEntityUpdate iupdate; 4024 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3978 Int32 timeinqueue; // this is just debugging code & can be dropped later 4025 break;
3979 4026
3980 while (updatesThisCall < maxUpdates) 4027 EntityUpdate update = (EntityUpdate)iupdate;
4028
4029// avgTimeDilation += update.TimeDilation;
4030
4031 if (update.Entity is SceneObjectPart)
3981 { 4032 {
3982 lock (m_entityUpdates.SyncRoot) 4033 SceneObjectPart part = (SceneObjectPart)update.Entity;
3983 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3984 break;
3985 4034
3986 EntityUpdate update = (EntityUpdate)iupdate; 4035 if (part.ParentGroup.IsDeleted || part.ParentGroup.inTransit)
3987 4036 continue;
3988 avgTimeDilation += update.TimeDilation;
3989 avgTimeDilation *= 0.5f;
3990 4037
3991 if (update.Entity is SceneObjectPart) 4038 if (part.ParentGroup.IsAttachment)
3992 { 4039 { // Someone else's HUD, why are we getting these?
3993 SceneObjectPart part = (SceneObjectPart)update.Entity; 4040 if (part.ParentGroup.OwnerID != AgentId && part.ParentGroup.HasPrivateAttachmentPoint)
3994
3995 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3996 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3997 // safety measure.
3998 //
3999 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
4000 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
4001 // updates and kills on different threads with different scheduling strategies, hence this protection.
4002 //
4003 // This doesn't appear to apply to child prims - a client will happily ignore these updates
4004 // after the root prim has been deleted.
4005 if (m_killRecord.Contains(part.LocalId))
4006 {
4007 // m_log.WarnFormat(
4008 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
4009 // part.LocalId, Name);
4010 continue; 4041 continue;
4011 } 4042 ScenePresence sp;
4012 4043 // Owner is not in the sim, don't update it to
4013 if (part.ParentGroup.IsAttachment && m_disableFacelights) 4044 // anyone
4045 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
4046 continue;
4047
4048 List<SceneObjectGroup> atts = sp.GetAttachments();
4049 bool found = false;
4050 foreach (SceneObjectGroup att in atts)
4014 { 4051 {
4015 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 4052 if (att == part.ParentGroup)
4016 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
4017 { 4053 {
4018 part.Shape.LightEntry = false; 4054 found = true;
4055 break;
4019 } 4056 }
4020 } 4057 }
4021 4058
4059 // It's an attachment of a valid avatar, but
4060 // doesn't seem to be attached, skip
4061 if (!found)
4062 continue;
4063
4064 // On vehicle crossing, the attachments are received
4065 // while the avatar is still a child. Don't send
4066 // updates here because the LocalId has not yet
4067 // been updated and the viewer will derender the
4068 // attachments until the avatar becomes root.
4069 if (sp.IsChildAgent)
4070 continue;
4071
4072 }
4073
4074 if (part.ParentGroup.IsAttachment && m_disableFacelights)
4075 {
4076 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
4077 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
4078 {
4079 part.Shape.LightEntry = false;
4080 }
4081
4022 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh)) 4082 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
4023 { 4083 {
4024 // Ensure that mesh has at least 8 valid faces 4084 // Ensure that mesh has at least 8 valid faces
@@ -4027,233 +4087,218 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4027 part.Shape.ProfileHollow = 27500; 4087 part.Shape.ProfileHollow = 27500;
4028 } 4088 }
4029 } 4089 }
4030 4090
4031 #region UpdateFlags to packet type conversion 4091 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
4032
4033 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
4034
4035 bool canUseCompressed = true;
4036 bool canUseImproved = true;
4037
4038 // Compressed object updates only make sense for LL primitives
4039 if (!(update.Entity is SceneObjectPart))
4040 { 4092 {
4041 canUseCompressed = false; 4093 // Ensure that mesh has at least 8 valid faces
4094 part.Shape.ProfileBegin = 12500;
4095 part.Shape.ProfileEnd = 0;
4096 part.Shape.ProfileHollow = 27500;
4042 } 4097 }
4043 4098 }
4044 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 4099 else if (update.Entity is ScenePresence)
4100 {
4101 ScenePresence presence = (ScenePresence)update.Entity;
4102 if (presence.IsDeleted)
4103 continue;
4104 // If ParentUUID is not UUID.Zero and ParentID is 0, this
4105 // avatar is in the process of crossing regions while
4106 // sat on an object. In this state, we don't want any
4107 // updates because they will visually orbit the avatar.
4108 // Update will be forced once crossing is completed anyway.
4109 if (presence.ParentUUID != UUID.Zero && presence.ParentID == 0)
4110 continue;
4111 }
4112
4113 ++updatesThisCall;
4114
4115 #region UpdateFlags to packet type conversion
4116
4117 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
4118
4119 bool canUseCompressed = true;
4120 bool canUseImproved = true;
4121
4122 // Compressed object updates only make sense for LL primitives
4123 if (!(update.Entity is SceneObjectPart))
4124 {
4125 canUseCompressed = false;
4126 }
4127
4128 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
4129 {
4130 canUseCompressed = false;
4131 canUseImproved = false;
4132 }
4133 else
4134 {
4135 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
4136 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
4137 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
4138 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4045 { 4139 {
4046 canUseCompressed = false; 4140 canUseCompressed = false;
4047 canUseImproved = false;
4048 } 4141 }
4049 else 4142
4143 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
4144 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
4145 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
4146 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
4147 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
4148 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
4149 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
4150 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
4151 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
4152 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
4153 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
4154 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
4155 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
4156 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4050 { 4157 {
4051 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 4158 canUseImproved = false;
4052 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
4053 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
4054 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4055 {
4056 canUseCompressed = false;
4057 }
4058
4059 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
4060 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
4061 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
4062 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
4063 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
4064 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
4065 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
4066 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
4067 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
4068 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
4069 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
4070 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
4071 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
4072 updateFlags.HasFlag(PrimUpdateFlags.Joint))
4073 {
4074 canUseImproved = false;
4075 }
4076 } 4159 }
4160 }
4077 4161
4078 #endregion UpdateFlags to packet type conversion 4162 #endregion UpdateFlags to packet type conversion
4079
4080 #region Block Construction
4081
4082 // TODO: Remove this once we can build compressed updates
4083 canUseCompressed = false;
4084
4085 if (!canUseImproved && !canUseCompressed)
4086 {
4087 ObjectUpdatePacket.ObjectDataBlock updateBlock;
4088 4163
4089 if (update.Entity is ScenePresence) 4164 #region Block Construction
4090 {
4091 updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
4092 }
4093 else
4094 {
4095 SceneObjectPart part = (SceneObjectPart)update.Entity;
4096 updateBlock = CreatePrimUpdateBlock(part, AgentId);
4097
4098 // If the part has become a private hud since the update was scheduled then we do not
4099 // want to send it to other avatars.
4100 if (part.ParentGroup.IsAttachment
4101 && part.ParentGroup.HasPrivateAttachmentPoint
4102 && part.ParentGroup.AttachedAvatar != AgentId)
4103 continue;
4104
4105 // If the part has since been deleted, then drop the update. In the case of attachments,
4106 // this is to avoid spurious updates to other viewers since post-processing of attachments
4107 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4108 // of the test above).
4109 //
4110 // Actual deletions (kills) happen in another method.
4111 if (part.ParentGroup.IsDeleted)
4112 continue;
4113 }
4114 4165
4115 objectUpdateBlocks.Value.Add(updateBlock); 4166 // TODO: Remove this once we can build compressed updates
4116 objectUpdates.Value.Add(update); 4167 canUseCompressed = false;
4117 }
4118 else if (!canUseImproved)
4119 {
4120 SceneObjectPart part = (SceneObjectPart)update.Entity;
4121 ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
4122 = CreateCompressedUpdateBlock(part, updateFlags);
4123
4124 // If the part has since been deleted, then drop the update. In the case of attachments,
4125 // this is to avoid spurious updates to other viewers since post-processing of attachments
4126 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4127 // of the test above).
4128 //
4129 // Actual deletions (kills) happen in another method.
4130 if (part.ParentGroup.IsDeleted)
4131 continue;
4132 4168
4133 compressedUpdateBlocks.Value.Add(compressedBlock); 4169 if (!canUseImproved && !canUseCompressed)
4134 compressedUpdates.Value.Add(update); 4170 {
4171 if (update.Entity is ScenePresence)
4172 {
4173 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
4135 } 4174 }
4136 else 4175 else
4137 { 4176 {
4138 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 4177 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
4139 { 4178 }
4140 // Self updates go into a special list 4179 }
4141 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 4180 else if (!canUseImproved)
4142 terseAgentUpdates.Value.Add(update); 4181 {
4143 } 4182 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
4144 else 4183 }
4145 { 4184 else
4146 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock 4185 {
4147 = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)); 4186 if (update.Entity is ScenePresence)
4187 // ALL presence updates go into a special list
4188 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
4189 else
4190 // Everything else goes here
4191 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
4192 }
4148 4193
4149 // Everything else goes here 4194 #endregion Block Construction
4150 if (update.Entity is SceneObjectPart) 4195 }
4151 {
4152 SceneObjectPart part = (SceneObjectPart)update.Entity;
4153
4154 // If the part has become a private hud since the update was scheduled then we do not
4155 // want to send it to other avatars.
4156 if (part.ParentGroup.IsAttachment
4157 && part.ParentGroup.HasPrivateAttachmentPoint
4158 && part.ParentGroup.AttachedAvatar != AgentId)
4159 continue;
4160
4161 // If the part has since been deleted, then drop the update. In the case of attachments,
4162 // this is to avoid spurious updates to other viewers since post-processing of attachments
4163 // has to change the IsAttachment flag for various reasons (which will end up in a pass
4164 // of the test above).
4165 //
4166 // Actual deletions (kills) happen in another method.
4167 if (part.ParentGroup.IsDeleted)
4168 continue;
4169 }
4170 4196
4171 terseUpdateBlocks.Value.Add(terseUpdateBlock); 4197 #region Packet Sending
4172 terseUpdates.Value.Add(update); 4198
4173 } 4199// const float TIME_DILATION = 1.0f;
4174 } 4200 ushort timeDilation;
4201// if(updatesThisCall > 0)
4202// timeDilation = Utils.FloatToUInt16(avgTimeDilation/updatesThisCall, 0.0f, 1.0f);
4203// else
4204// timeDilation = ushort.MaxValue; // 1.0;
4205
4206 timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
4175 4207
4176 ++updatesThisCall; 4208 if (terseAgentUpdateBlocks.IsValueCreated)
4209 {
4210 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
4211
4212 ImprovedTerseObjectUpdatePacket packet
4213 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
4214 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4215 packet.RegionData.TimeDilation = timeDilation;
4216 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4217
4218 for (int i = 0; i < blocks.Count; i++)
4219 packet.ObjectData[i] = blocks[i];
4220
4221 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4222 }
4223
4224 if (objectUpdateBlocks.IsValueCreated)
4225 {
4226 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
4177 4227
4178 #endregion Block Construction 4228 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4179 } 4229 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4230 packet.RegionData.TimeDilation = timeDilation;
4231 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4232
4233 for (int i = 0; i < blocks.Count; i++)
4234 packet.ObjectData[i] = blocks[i];
4180 4235
4181 #region Packet Sending 4236 OutPacket(packet, ThrottleOutPacketType.Task, true);
4182 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 4237 }
4238
4239 if (compressedUpdateBlocks.IsValueCreated)
4240 {
4241 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
4242
4243 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4244 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4245 packet.RegionData.TimeDilation = timeDilation;
4246 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4183 4247
4184 if (terseAgentUpdateBlocks.IsValueCreated) 4248 for (int i = 0; i < blocks.Count; i++)
4185 { 4249 packet.ObjectData[i] = blocks[i];
4186 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 4250
4251 OutPacket(packet, ThrottleOutPacketType.Task, true);
4252 }
4253
4254 if (terseUpdateBlocks.IsValueCreated)
4255 {
4256 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4257
4258 ImprovedTerseObjectUpdatePacket packet
4259 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4260 PacketType.ImprovedTerseObjectUpdate);
4261 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4262 packet.RegionData.TimeDilation = timeDilation;
4263 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4264
4265 for (int i = 0; i < blocks.Count; i++)
4266 packet.ObjectData[i] = blocks[i];
4187 4267
4188 ImprovedTerseObjectUpdatePacket packet 4268 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4189 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 4269 }
4190 4270
4191 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4271 #endregion Packet Sending
4192 packet.RegionData.TimeDilation = timeDilation; 4272 }
4193 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4194 4273
4195 for (int i = 0; i < blocks.Count; i++) 4274 // hack.. dont use
4196 packet.ObjectData[i] = blocks[i]; 4275 public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
4197 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4276 {
4198 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); 4277 if (ent is SceneObjectPart)
4199 } 4278 {
4279 SceneObjectPart part = (SceneObjectPart)ent;
4280 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4281 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4282 packet.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
4283 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
4200 4284
4201 if (objectUpdateBlocks.IsValueCreated) 4285 ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, this.m_agentId);
4202 { 4286 if (parentID.HasValue)
4203 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
4204
4205 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4206 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4207 packet.RegionData.TimeDilation = timeDilation;
4208 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4209
4210 for (int i = 0; i < blocks.Count; i++)
4211 packet.ObjectData[i] = blocks[i];
4212 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4213 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
4214 }
4215
4216 if (compressedUpdateBlocks.IsValueCreated)
4217 { 4287 {
4218 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; 4288 blk.ParentID = parentID.Value;
4219
4220 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4221 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4222 packet.RegionData.TimeDilation = timeDilation;
4223 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4224
4225 for (int i = 0; i < blocks.Count; i++)
4226 packet.ObjectData[i] = blocks[i];
4227 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4228 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
4229 } 4289 }
4230 4290
4231 if (terseUpdateBlocks.IsValueCreated) 4291 packet.ObjectData[0] = blk;
4232 {
4233 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4234
4235 ImprovedTerseObjectUpdatePacket packet
4236 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4237 PacketType.ImprovedTerseObjectUpdate);
4238 4292
4239 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4293 OutPacket(packet, ThrottleOutPacketType.Task, true);
4240 packet.RegionData.TimeDilation = timeDilation;
4241 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4242
4243 for (int i = 0; i < blocks.Count; i++)
4244 packet.ObjectData[i] = blocks[i];
4245 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
4246 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4247 }
4248 } 4294 }
4249 4295
4250// m_log.DebugFormat( 4296// m_log.DebugFormat(
4251// "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}", 4297// "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}",
4252// updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name); 4298// updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name);
4253// 4299//
4254 #endregion Packet Sending
4255 } 4300 }
4256 4301
4257 public void ReprioritizeUpdates() 4302 public void ReprioritizeUpdates()
4258 { 4303 {
4259 lock (m_entityUpdates.SyncRoot) 4304 lock (m_entityUpdates.SyncRoot)
@@ -4572,11 +4617,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4572 4617
4573 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4618 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4574 // of the object rather than the properties when the packet was created 4619 // of the object rather than the properties when the packet was created
4575 OutPacket(packet, ThrottleOutPacketType.Task, true, 4620 // HACK : Remove intelligent resending until it's fixed in core
4576 delegate(OutgoingPacket oPacket) 4621 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4577 { 4622 // delegate(OutgoingPacket oPacket)
4578 ResendPropertyUpdates(updates, oPacket); 4623 // {
4579 }); 4624 // ResendPropertyUpdates(updates, oPacket);
4625 // });
4626 OutPacket(packet, ThrottleOutPacketType.Task, true);
4580 4627
4581 // pbcnt += blocks.Count; 4628 // pbcnt += blocks.Count;
4582 // ppcnt++; 4629 // ppcnt++;
@@ -4602,11 +4649,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4602 // of the object rather than the properties when the packet was created 4649 // of the object rather than the properties when the packet was created
4603 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4650 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4604 updates.Add(familyUpdates.Value[i]); 4651 updates.Add(familyUpdates.Value[i]);
4605 OutPacket(packet, ThrottleOutPacketType.Task, true, 4652 // HACK : Remove intelligent resending until it's fixed in core
4606 delegate(OutgoingPacket oPacket) 4653 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4607 { 4654 // delegate(OutgoingPacket oPacket)
4608 ResendPropertyUpdates(updates, oPacket); 4655 // {
4609 }); 4656 // ResendPropertyUpdates(updates, oPacket);
4657 // });
4658 OutPacket(packet, ThrottleOutPacketType.Task, true);
4610 4659
4611 // fpcnt++; 4660 // fpcnt++;
4612 // fbcnt++; 4661 // fbcnt++;
@@ -4939,7 +4988,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4939 packet.ParcelData.Data = data; 4988 packet.ParcelData.Data = data;
4940 packet.ParcelData.SequenceID = sequence_id; 4989 packet.ParcelData.SequenceID = sequence_id;
4941 packet.Header.Zerocoded = true; 4990 packet.Header.Zerocoded = true;
4942 OutPacket(packet, ThrottleOutPacketType.Task); 4991// OutPacket(packet, ThrottleOutPacketType.Task);
4992 OutPacket(packet, ThrottleOutPacketType.Land);
4943 } 4993 }
4944 4994
4945 public void SendLandProperties( 4995 public void SendLandProperties(
@@ -5004,7 +5054,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5004 5054
5005 if (landData.SimwideArea > 0) 5055 if (landData.SimwideArea > 0)
5006 { 5056 {
5007 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 5057 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
5058 // Never report more than sim total capacity
5059 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
5060 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
5008 updateMessage.SimWideMaxPrims = simulatorCapacity; 5061 updateMessage.SimWideMaxPrims = simulatorCapacity;
5009 } 5062 }
5010 else 5063 else
@@ -5039,7 +5092,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5039 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>(); 5092 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
5040 if (eq != null) 5093 if (eq != null)
5041 { 5094 {
5042 eq.ParcelProperties(updateMessage, this.AgentId); 5095
5096 OSD message_body = updateMessage.Serialize();
5097 // Add new fields here until OMV has them
5098 OSDMap bodyMap = (OSDMap)message_body;
5099 OSDArray parcelDataArray = (OSDArray)bodyMap["ParcelData"];
5100 OSDMap parcelData = (OSDMap)parcelDataArray[0];
5101 parcelData["SeeAVs"] = OSD.FromBoolean(landData.SeeAVs);
5102 parcelData["AnyAVSounds"] = OSD.FromBoolean(landData.AnyAVSounds);
5103 parcelData["GroupAVSounds"] = OSD.FromBoolean(landData.GroupAVSounds);
5104 OSDMap message = new OSDMap();
5105 message.Add("message", OSD.FromString("ParcelProperties"));
5106 message.Add("body", message_body);
5107
5108 eq.Enqueue (message, this.AgentId);
5109
5110// eq.ParcelProperties(updateMessage, this.AgentId);
5043 } 5111 }
5044 else 5112 else
5045 { 5113 {
@@ -5133,14 +5201,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5133 5201
5134 if (notifyCount > 0) 5202 if (notifyCount > 0)
5135 { 5203 {
5136 if (notifyCount > 32) 5204// if (notifyCount > 32)
5137 { 5205// {
5138 m_log.InfoFormat( 5206// m_log.InfoFormat(
5139 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 5207// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
5140 + " - a developer might want to investigate whether this is a hard limit", 32); 5208// + " - a developer might want to investigate whether this is a hard limit", 32);
5141 5209//
5142 notifyCount = 32; 5210// notifyCount = 32;
5143 } 5211// }
5144 5212
5145 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 5213 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
5146 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 5214 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -5195,41 +5263,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5195 { 5263 {
5196 ScenePresence presence = (ScenePresence)entity; 5264 ScenePresence presence = (ScenePresence)entity;
5197 5265
5198// m_log.DebugFormat(
5199// "[LLCLIENTVIEW]: Sending terse update to {0} with pos {1}, vel {2} in {3}",
5200// Name, presence.OffsetPosition, presence.Velocity, m_scene.Name);
5201
5202 attachPoint = presence.State;
5203 collisionPlane = presence.CollisionPlane;
5204 position = presence.OffsetPosition; 5266 position = presence.OffsetPosition;
5205 velocity = presence.Velocity; 5267 rotation = presence.Rotation;
5206 acceleration = Vector3.Zero;
5207
5208 // Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating
5209 // in that direction, even though we don't model this on the server. Implementing this in the future
5210 // may improve movement smoothness.
5211// acceleration = new Vector3(1, 0, 0);
5212
5213 angularVelocity = presence.AngularVelocity; 5268 angularVelocity = presence.AngularVelocity;
5214
5215 // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis
5216 // it rotates around.
5217 // In mouselook, X and Y co-ordinate will also be sent but when used in Rotation, these cause unwanted
5218 // excessive up and down movements of the camera when looking up and down.
5219 // See http://opensimulator.org/mantis/view.php?id=3274
5220 // This does not affect head movement, since this is controlled entirely by camera movement rather than
5221 // body rotation. We still need to transmit X and Y for sitting avatars but mouselook does not change
5222 // the rotation in this case.
5223 rotation = presence.Rotation; 5269 rotation = presence.Rotation;
5224 5270
5225 if (!presence.IsSatOnObject) 5271 attachPoint = 0;
5226 { 5272// m_log.DebugFormat(
5227 rotation.X = 0; 5273// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5228 rotation.Y = 0; 5274
5229 } 5275 // attachPoint = presence.State; // Core: commented
5276 collisionPlane = presence.CollisionPlane;
5277 velocity = presence.Velocity;
5278 acceleration = Vector3.Zero;
5230 5279
5231 if (sendTexture) 5280 if (sendTexture)
5281 {
5232 textureEntry = presence.Appearance.Texture.GetBytes(); 5282 textureEntry = presence.Appearance.Texture.GetBytes();
5283 }
5233 else 5284 else
5234 textureEntry = null; 5285 textureEntry = null;
5235 } 5286 }
@@ -5333,34 +5384,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5333 5384
5334 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5385 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5335 { 5386 {
5387 Vector3 offsetPosition = data.OffsetPosition;
5388 Quaternion rotation = data.Rotation;
5389 uint parentID = data.ParentID;
5390
5336// m_log.DebugFormat( 5391// m_log.DebugFormat(
5337// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name); 5392// "[LLCLIENTVIEW]: Sending full update to {0} with pos {1}, vel {2} in {3}", Name, data.OffsetPosition, data.Velocity, m_scene.Name);
5338 5393
5339 byte[] objectData = new byte[76]; 5394 byte[] objectData = new byte[76];
5340 5395
5341 data.CollisionPlane.ToBytes(objectData, 0); 5396 Vector3 velocity = new Vector3(0, 0, 0);
5342 data.OffsetPosition.ToBytes(objectData, 16); 5397 Vector3 acceleration = new Vector3(0, 0, 0);
5343 data.Velocity.ToBytes(objectData, 28); 5398 rotation.Normalize();
5344// data.Acceleration.ToBytes(objectData, 40);
5345
5346 // Whilst not in mouselook, an avatar will transmit only the Z rotation as this is the only axis
5347 // it rotates around.
5348 // In mouselook, X and Y co-ordinate will also be sent but when used in Rotation, these cause unwanted
5349 // excessive up and down movements of the camera when looking up and down.
5350 // See http://opensimulator.org/mantis/view.php?id=3274
5351 // This does not affect head movement, since this is controlled entirely by camera movement rather than
5352 // body rotation. We still need to transmit X and Y for sitting avatars but mouselook does not change
5353 // the rotation in this case.
5354 Quaternion rot = data.Rotation;
5355
5356 if (!data.IsSatOnObject)
5357 {
5358 rot.X = 0;
5359 rot.Y = 0;
5360 }
5361 5399
5362 rot.ToBytes(objectData, 52); 5400 data.CollisionPlane.ToBytes(objectData, 0);
5363 //data.AngularVelocity.ToBytes(objectData, 64); 5401 offsetPosition.ToBytes(objectData, 16);
5402 velocity.ToBytes(objectData, 28);
5403 acceleration.ToBytes(objectData, 40);
5404 rotation.ToBytes(objectData, 52);
5405 data.AngularVelocity.ToBytes(objectData, 64);
5364 5406
5365 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5407 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
5366 5408
@@ -5386,7 +5428,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5386 update.PCode = (byte)PCode.Avatar; 5428 update.PCode = (byte)PCode.Avatar;
5387 update.ProfileCurve = 1; 5429 update.ProfileCurve = 1;
5388 update.PSBlock = Utils.EmptyBytes; 5430 update.PSBlock = Utils.EmptyBytes;
5389 update.Scale = new Vector3(0.45f, 0.6f, 1.9f); 5431 update.Scale = data.Appearance.AvatarSize;
5432// update.Scale.Z -= 0.2f;
5433
5390 update.Text = Utils.EmptyBytes; 5434 update.Text = Utils.EmptyBytes;
5391 update.TextColor = new byte[4]; 5435 update.TextColor = new byte[4];
5392 5436
@@ -5397,10 +5441,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5397 update.TextureEntry = Utils.EmptyBytes; 5441 update.TextureEntry = Utils.EmptyBytes;
5398// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; 5442// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
5399 5443
5444/* all this flags seem related to prims and not avatars. This allow for wrong viewer side move of a avatar in prim edition mode (anv mantis 854)
5400 update.UpdateFlags = (uint)( 5445 update.UpdateFlags = (uint)(
5401 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | 5446 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
5402 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | 5447 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
5403 PrimFlags.ObjectOwnerModify); 5448 PrimFlags.ObjectOwnerModify);
5449*/
5450 update.UpdateFlags = 0;
5404 5451
5405 return update; 5452 return update;
5406 } 5453 }
@@ -5411,15 +5458,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5411 data.RelativePosition.ToBytes(objectData, 0); 5458 data.RelativePosition.ToBytes(objectData, 0);
5412 data.Velocity.ToBytes(objectData, 12); 5459 data.Velocity.ToBytes(objectData, 12);
5413 data.Acceleration.ToBytes(objectData, 24); 5460 data.Acceleration.ToBytes(objectData, 24);
5414 try 5461
5415 { 5462 Quaternion rotation = data.RotationOffset;
5416 data.RotationOffset.ToBytes(objectData, 36); 5463 rotation.Normalize();
5417 } 5464 rotation.ToBytes(objectData, 36);
5418 catch (Exception e)
5419 {
5420 m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString());
5421 OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36);
5422 }
5423 data.AngularVelocity.ToBytes(objectData, 48); 5465 data.AngularVelocity.ToBytes(objectData, 48);
5424 5466
5425 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5467 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5433,7 +5475,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5433 //update.JointType = 0; 5475 //update.JointType = 0;
5434 update.Material = data.Material; 5476 update.Material = data.Material;
5435 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim 5477 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
5436 5478/*
5437 if (data.ParentGroup.IsAttachment) 5479 if (data.ParentGroup.IsAttachment)
5438 { 5480 {
5439 update.NameValue 5481 update.NameValue
@@ -5458,6 +5500,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5458 // case for attachments may contain conflicting values that can end up crashing the viewer. 5500 // case for attachments may contain conflicting values that can end up crashing the viewer.
5459 update.State = data.ParentGroup.RootPart.Shape.State; 5501 update.State = data.ParentGroup.RootPart.Shape.State;
5460 } 5502 }
5503*/
5504
5505 if (data.ParentGroup.IsAttachment)
5506 {
5507 if (data.IsRoot)
5508 {
5509 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID);
5510 }
5511 else
5512 update.NameValue = Utils.EmptyBytes;
5513
5514 int st = (int)data.ParentGroup.AttachmentPoint;
5515 update.State = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
5516 }
5517 else
5518 {
5519 update.NameValue = Utils.EmptyBytes;
5520 update.State = data.Shape.State; // not sure about this
5521 }
5522
5461 5523
5462 update.ObjectData = objectData; 5524 update.ObjectData = objectData;
5463 update.ParentID = data.ParentID; 5525 update.ParentID = data.ParentID;
@@ -5579,8 +5641,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5579 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs 5641 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5580 // for each AgentUpdate packet. 5642 // for each AgentUpdate packet.
5581 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5643 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5582 5644
5583 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5645 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5646 AddLocalPacketHandler(PacketType.VelocityInterpolateOff, HandleVelocityInterpolateOff, false);
5647 AddLocalPacketHandler(PacketType.VelocityInterpolateOn, HandleVelocityInterpolateOn, false);
5584 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5648 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5585 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5649 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5586 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5650 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
@@ -5732,6 +5796,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5732 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5796 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5733 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5797 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5734 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5798 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5799 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5735 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5800 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5736 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5801 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5737 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5802 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5798,6 +5863,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5798 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5863 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5799 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5864 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5800 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5865 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5866 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5801 5867
5802 AddGenericPacketHandler("autopilot", HandleAutopilot); 5868 AddGenericPacketHandler("autopilot", HandleAutopilot);
5803 } 5869 }
@@ -5809,7 +5875,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5809 #region Scene/Avatar 5875 #region Scene/Avatar
5810 5876
5811 // Threshold for body rotation to be a significant agent update 5877 // Threshold for body rotation to be a significant agent update
5812 private const float QDELTA = 0.000001f; 5878 // use the abs of cos
5879 private const float QDELTABody = 1.0f - 0.0001f;
5880 private const float QDELTAHead = 1.0f - 0.0001f;
5813 // Threshold for camera rotation to be a significant agent update 5881 // Threshold for camera rotation to be a significant agent update
5814 private const float VDELTA = 0.01f; 5882 private const float VDELTA = 0.01f;
5815 5883
@@ -5832,18 +5900,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5832 /// <param name='x'></param> 5900 /// <param name='x'></param>
5833 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) 5901 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5834 { 5902 {
5835 float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2); 5903 float qdelta1 = Math.Abs(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation));
5836 //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2); 5904 //qdelta2 = Math.Abs(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation));
5837 5905
5838 bool movementSignificant = 5906 bool movementSignificant =
5839 (qdelta1 > QDELTA) // significant if body rotation above threshold 5907 (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5840 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5841 // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold
5842 || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5843 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands 5908 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands
5844 || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed
5845 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed 5909 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed
5846 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed 5910 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed
5911 || (qdelta1 < QDELTABody) // significant if body rotation above(below cos) threshold
5912 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5913 // || (qdelta2 < QDELTAHead) // significant if head rotation above(below cos) threshold
5914 || (Math.Abs(x.Far - m_thisAgentUpdateArgs.Far) >= 32) // significant if far distance changed
5847 ; 5915 ;
5848 //if (movementSignificant) 5916 //if (movementSignificant)
5849 //{ 5917 //{
@@ -5886,55 +5954,63 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5886 return cameraSignificant; 5954 return cameraSignificant;
5887 } 5955 }
5888 5956
5889 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 5957 private bool HandleAgentUpdate(IClientAPI sender, Packet packet)
5890 { 5958 {
5891 // We got here, which means that something in agent update was significant 5959 // We got here, which means that something in agent update was significant
5892 5960
5893 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; 5961 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5894 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 5962 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5895 5963
5896 if (x.AgentID != AgentId || x.SessionID != SessionId) 5964 if (x.AgentID != AgentId || x.SessionID != SessionId)
5965 {
5966 PacketPool.Instance.ReturnPacket(packet);
5897 return false; 5967 return false;
5968 }
5969
5970 TotalAgentUpdates++;
5898 5971
5899 // Before we update the current m_thisAgentUpdateArgs, let's check this again
5900 // to see what exactly changed
5901 bool movement = CheckAgentMovementUpdateSignificance(x); 5972 bool movement = CheckAgentMovementUpdateSignificance(x);
5902 bool camera = CheckAgentCameraUpdateSignificance(x); 5973 bool camera = CheckAgentCameraUpdateSignificance(x);
5903 5974
5904 m_thisAgentUpdateArgs.AgentID = x.AgentID;
5905 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5906 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5907 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
5908 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5909 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5910 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5911 m_thisAgentUpdateArgs.Far = x.Far;
5912 m_thisAgentUpdateArgs.Flags = x.Flags;
5913 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5914 m_thisAgentUpdateArgs.SessionID = x.SessionID;
5915 m_thisAgentUpdateArgs.State = x.State;
5916
5917 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5918 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5919 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
5920
5921 // Was there a significant movement/state change? 5975 // Was there a significant movement/state change?
5922 if (movement) 5976 if (movement)
5923 { 5977 {
5978 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5979 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5980 m_thisAgentUpdateArgs.Far = x.Far;
5981 m_thisAgentUpdateArgs.Flags = x.Flags;
5982 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5983// m_thisAgentUpdateArgs.SessionID = x.SessionID;
5984 m_thisAgentUpdateArgs.State = x.State;
5985
5986 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5987 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5988
5924 if (handlerPreAgentUpdate != null) 5989 if (handlerPreAgentUpdate != null)
5925 OnPreAgentUpdate(this, m_thisAgentUpdateArgs); 5990 OnPreAgentUpdate(this, m_thisAgentUpdateArgs);
5926 5991
5927 if (handlerAgentUpdate != null) 5992 if (handlerAgentUpdate != null)
5928 OnAgentUpdate(this, m_thisAgentUpdateArgs); 5993 OnAgentUpdate(this, m_thisAgentUpdateArgs);
5994
5995 handlerAgentUpdate = null;
5996 handlerPreAgentUpdate = null;
5929 } 5997 }
5998
5930 // Was there a significant camera(s) change? 5999 // Was there a significant camera(s) change?
5931 if (camera) 6000 if (camera)
6001 {
6002 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
6003 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
6004 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
6005 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
6006
6007 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
6008
5932 if (handlerAgentCameraUpdate != null) 6009 if (handlerAgentCameraUpdate != null)
5933 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs); 6010 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs);
5934 6011
5935 handlerAgentUpdate = null; 6012 handlerAgentCameraUpdate = null;
5936 handlerPreAgentUpdate = null; 6013 }
5937 handlerAgentCameraUpdate = null;
5938 6014
5939 PacketPool.Instance.ReturnPacket(packet); 6015 PacketPool.Instance.ReturnPacket(packet);
5940 6016
@@ -6150,6 +6226,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6150 return true; 6226 return true;
6151 } 6227 }
6152 6228
6229 private bool HandleVelocityInterpolateOff(IClientAPI sender, Packet Pack)
6230 {
6231 VelocityInterpolateOffPacket p = (VelocityInterpolateOffPacket)Pack;
6232 if (p.AgentData.SessionID != SessionId ||
6233 p.AgentData.AgentID != AgentId)
6234 return true;
6235
6236 m_VelocityInterpolate = false;
6237 return true;
6238 }
6239
6240 private bool HandleVelocityInterpolateOn(IClientAPI sender, Packet Pack)
6241 {
6242 VelocityInterpolateOnPacket p = (VelocityInterpolateOnPacket)Pack;
6243 if (p.AgentData.SessionID != SessionId ||
6244 p.AgentData.AgentID != AgentId)
6245 return true;
6246
6247 m_VelocityInterpolate = true;
6248 return true;
6249 }
6250
6251
6153 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack) 6252 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack)
6154 { 6253 {
6155 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; 6254 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
@@ -6503,7 +6602,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6503 { 6602 {
6504 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore, 6603 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
6505 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit. 6604 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
6506 m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
6507 if (OnModifyTerrain != null) 6605 if (OnModifyTerrain != null)
6508 { 6606 {
6509 for (int i = 0; i < modify.ParcelData.Length; i++) 6607 for (int i = 0; i < modify.ParcelData.Length; i++)
@@ -6519,7 +6617,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6519 } 6617 }
6520 } 6618 }
6521 } 6619 }
6522 m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
6523 } 6620 }
6524 6621
6525 return true; 6622 return true;
@@ -6581,16 +6678,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6581 for (int i = 0; i < appear.VisualParam.Length; i++) 6678 for (int i = 0; i < appear.VisualParam.Length; i++)
6582 visualparams[i] = appear.VisualParam[i].ParamValue; 6679 visualparams[i] = appear.VisualParam[i].ParamValue;
6583 //var b = appear.WearableData[0]; 6680 //var b = appear.WearableData[0];
6584 6681
6585 Primitive.TextureEntry te = null; 6682 Primitive.TextureEntry te = null;
6586 if (appear.ObjectData.TextureEntry.Length > 1) 6683 if (appear.ObjectData.TextureEntry.Length > 1)
6587 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); 6684 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
6588 6685
6589 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length]; 6686 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length];
6590 for (int i=0; i<appear.WearableData.Length;i++) 6687 for (int i=0; i<appear.WearableData.Length;i++)
6591 cacheitems[i] = new WearableCacheItem(){CacheId = appear.WearableData[i].CacheID,TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)}; 6688 cacheitems[i] = new WearableCacheItem(){
6592 6689 CacheId = appear.WearableData[i].CacheID,
6690 TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)
6691 };
6593 6692
6693
6594 6694
6595 handlerSetAppearance(sender, te, visualparams,avSize, cacheitems); 6695 handlerSetAppearance(sender, te, visualparams,avSize, cacheitems);
6596 } 6696 }
@@ -6794,13 +6894,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6794 return true; 6894 return true;
6795 } 6895 }
6796 6896
6797 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) 6897 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
6798 { 6898 {
6899 m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement");
6900
6799 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion; 6901 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
6800 if (handlerCompleteMovementToRegion != null) 6902 if (handlerCompleteMovementToRegion != null)
6801 { 6903 {
6802 handlerCompleteMovementToRegion(sender, true); 6904 handlerCompleteMovementToRegion(sender, true);
6803 } 6905 }
6906 else
6907 m_log.Debug("HandleCompleteAgentMovement NULL handler");
6908
6804 handlerCompleteMovementToRegion = null; 6909 handlerCompleteMovementToRegion = null;
6805 6910
6806 return true; 6911 return true;
@@ -6818,7 +6923,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6818 return true; 6923 return true;
6819 } 6924 }
6820 #endregion 6925 #endregion
6821 6926/*
6822 StartAnim handlerStartAnim = null; 6927 StartAnim handlerStartAnim = null;
6823 StopAnim handlerStopAnim = null; 6928 StopAnim handlerStopAnim = null;
6824 6929
@@ -6842,6 +6947,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6842 } 6947 }
6843 } 6948 }
6844 return true; 6949 return true;
6950*/
6951 ChangeAnim handlerChangeAnim = null;
6952
6953 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6954 {
6955 handlerChangeAnim = OnChangeAnim;
6956 if (handlerChangeAnim != null)
6957 {
6958 handlerChangeAnim(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
6959 }
6960 }
6961
6962 handlerChangeAnim = OnChangeAnim;
6963 if (handlerChangeAnim != null)
6964 {
6965 handlerChangeAnim(UUID.Zero, false, true);
6966 }
6967
6968 return true;
6845 } 6969 }
6846 6970
6847 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) 6971 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
@@ -7087,6 +7211,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7087 #endregion 7211 #endregion
7088 7212
7089 m_udpClient.SetThrottles(atpack.Throttle.Throttles); 7213 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
7214 GenericCall2 handler = OnUpdateThrottles;
7215 if (handler != null)
7216 {
7217 handler();
7218 }
7090 return true; 7219 return true;
7091 } 7220 }
7092 7221
@@ -7359,6 +7488,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7359 7488
7360 for (int i = 0; i < incomingselect.ObjectData.Length; i++) 7489 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
7361 { 7490 {
7491 if (!SelectedObjects.Contains(incomingselect.ObjectData[i].ObjectLocalID))
7492 SelectedObjects.Add(incomingselect.ObjectData[i].ObjectLocalID);
7362 handlerObjectSelect = OnObjectSelect; 7493 handlerObjectSelect = OnObjectSelect;
7363 if (handlerObjectSelect != null) 7494 if (handlerObjectSelect != null)
7364 { 7495 {
@@ -7385,6 +7516,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7385 7516
7386 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) 7517 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
7387 { 7518 {
7519 if (!SelectedObjects.Contains(incomingdeselect.ObjectData[i].ObjectLocalID))
7520 SelectedObjects.Add(incomingdeselect.ObjectData[i].ObjectLocalID);
7388 handlerObjectDeselect = OnObjectDeselect; 7521 handlerObjectDeselect = OnObjectDeselect;
7389 if (handlerObjectDeselect != null) 7522 if (handlerObjectDeselect != null)
7390 { 7523 {
@@ -7511,7 +7644,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7511 physdata.Bounce = phsblock.Restitution; 7644 physdata.Bounce = phsblock.Restitution;
7512 physdata.Density = phsblock.Density; 7645 physdata.Density = phsblock.Density;
7513 physdata.Friction = phsblock.Friction; 7646 physdata.Friction = phsblock.Friction;
7514 physdata.GravitationModifier = phsblock.GravityMultiplier; 7647 physdata.GravitationModifier = phsblock.GravityMultiplier;
7515 } 7648 }
7516 7649
7517 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this); 7650 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
@@ -8097,6 +8230,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8097 // surrounding scene 8230 // surrounding scene
8098 if ((ImageType)block.Type == ImageType.Baked) 8231 if ((ImageType)block.Type == ImageType.Baked)
8099 args.Priority *= 2.0f; 8232 args.Priority *= 2.0f;
8233 int wearableout = 0;
8100 8234
8101 ImageManager.EnqueueReq(args); 8235 ImageManager.EnqueueReq(args);
8102 } 8236 }
@@ -9106,7 +9240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9106 if ((locX >= m_scene.RegionInfo.WorldLocX) 9240 if ((locX >= m_scene.RegionInfo.WorldLocX)
9107 && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX)) 9241 && (locX < (m_scene.RegionInfo.WorldLocX + m_scene.RegionInfo.RegionSizeX))
9108 && (locY >= m_scene.RegionInfo.WorldLocY) 9242 && (locY >= m_scene.RegionInfo.WorldLocY)
9109 && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)) ) 9243 && (locY < (m_scene.RegionInfo.WorldLocY + m_scene.RegionInfo.RegionSizeY)))
9110 { 9244 {
9111 tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle; 9245 tpLocReq.Info.RegionHandle = m_scene.RegionInfo.RegionHandle;
9112 tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX; 9246 tpLocReq.Info.Position.X += locX - m_scene.RegionInfo.WorldLocX;
@@ -9146,16 +9280,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9146 9280
9147 #region Parcel related packets 9281 #region Parcel related packets
9148 9282
9283 // acumulate several HandleRegionHandleRequest consecutive overlaping requests
9284 // to be done with minimal resources as possible
9285 // variables temporary here while in test
9286
9287 Queue<UUID> RegionHandleRequests = new Queue<UUID>();
9288 bool RegionHandleRequestsInService = false;
9289
9149 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) 9290 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
9150 { 9291 {
9151 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 9292 UUID currentUUID;
9152 9293
9153 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; 9294 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
9154 if (handlerRegionHandleRequest != null) 9295
9296 if (handlerRegionHandleRequest == null)
9297 return true;
9298
9299 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
9300
9301 lock (RegionHandleRequests)
9155 { 9302 {
9156 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 9303 if (RegionHandleRequestsInService)
9304 {
9305 // we are already busy doing a previus request
9306 // so enqueue it
9307 RegionHandleRequests.Enqueue(rhrPack.RequestBlock.RegionID);
9308 return true;
9309 }
9310
9311 // else do it
9312 currentUUID = rhrPack.RequestBlock.RegionID;
9313 RegionHandleRequestsInService = true;
9157 } 9314 }
9158 return true; 9315
9316 while (true)
9317 {
9318 handlerRegionHandleRequest(this, currentUUID);
9319
9320 lock (RegionHandleRequests)
9321 {
9322 // exit condition, nothing to do or closed
9323 // current code seems to assume we may loose the handler at anytime,
9324 // so keep checking it
9325 handlerRegionHandleRequest = OnRegionHandleRequest;
9326
9327 if (RegionHandleRequests.Count == 0 || !IsActive || handlerRegionHandleRequest == null)
9328 {
9329 RegionHandleRequests.Clear();
9330 RegionHandleRequestsInService = false;
9331 return true;
9332 }
9333 currentUUID = RegionHandleRequests.Dequeue();
9334 }
9335 }
9336
9337 return true; // actually unreached
9159 } 9338 }
9160 9339
9161 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) 9340 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
@@ -10425,7 +10604,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10425 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 10604 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
10426 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 10605 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
10427 UpdateMuteListEntry.MuteData.MuteType, 10606 UpdateMuteListEntry.MuteData.MuteType,
10428 UpdateMuteListEntry.AgentData.AgentID); 10607 UpdateMuteListEntry.MuteData.MuteFlags);
10429 return true; 10608 return true;
10430 } 10609 }
10431 return false; 10610 return false;
@@ -10440,8 +10619,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10440 { 10619 {
10441 handlerRemoveMuteListEntry(this, 10620 handlerRemoveMuteListEntry(this,
10442 RemoveMuteListEntry.MuteData.MuteID, 10621 RemoveMuteListEntry.MuteData.MuteID,
10443 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 10622 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
10444 RemoveMuteListEntry.AgentData.AgentID);
10445 return true; 10623 return true;
10446 } 10624 }
10447 return false; 10625 return false;
@@ -10485,10 +10663,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10485 return false; 10663 return false;
10486 } 10664 }
10487 10665
10666 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
10667 {
10668 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
10669 (ChangeInventoryItemFlagsPacket)packet;
10670 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
10671 if (handlerChangeInventoryItemFlags != null)
10672 {
10673 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
10674 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
10675 return true;
10676 }
10677 return false;
10678 }
10679
10488 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 10680 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
10489 { 10681 {
10490 return true; 10682 return true;
10491 } 10683 }
10684
10685 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
10686 {
10687 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
10688
10689 #region Packet Session and User Check
10690 if (m_checkPackets)
10691 {
10692 if (packet.AgentData.SessionID != SessionId ||
10693 packet.AgentData.AgentID != AgentId)
10694 return true;
10695 }
10696 #endregion
10697 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
10698 List<InventoryItemBase> items = new List<InventoryItemBase>();
10699 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
10700 {
10701 InventoryItemBase b = new InventoryItemBase();
10702 b.ID = n.OldItemID;
10703 b.Folder = n.OldFolderID;
10704 items.Add(b);
10705 }
10706
10707 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
10708 if (handlerMoveItemsAndLeaveCopy != null)
10709 {
10710 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
10711 }
10712
10713 return true;
10714 }
10492 10715
10493 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 10716 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
10494 { 10717 {
@@ -10915,6 +11138,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10915 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 11138 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10916 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 11139 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10917 11140
11141 Scene scene = (Scene)m_scene;
11142 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
11143 {
11144 ScenePresence p;
11145 if (scene.TryGetScenePresence(sender.AgentId, out p))
11146 {
11147 if (p.GodLevel >= 200)
11148 {
11149 groupProfileReply.GroupData.OpenEnrollment = true;
11150 groupProfileReply.GroupData.MembershipFee = 0;
11151 }
11152 }
11153 }
11154
10918 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 11155 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10919 } 11156 }
10920 return true; 11157 return true;
@@ -11488,11 +11725,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11488 11725
11489 StartLure handlerStartLure = OnStartLure; 11726 StartLure handlerStartLure = OnStartLure;
11490 if (handlerStartLure != null) 11727 if (handlerStartLure != null)
11491 handlerStartLure(startLureRequest.Info.LureType, 11728 {
11492 Utils.BytesToString( 11729 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
11493 startLureRequest.Info.Message), 11730 {
11494 startLureRequest.TargetData[0].TargetID, 11731 handlerStartLure(startLureRequest.Info.LureType,
11495 this); 11732 Utils.BytesToString(
11733 startLureRequest.Info.Message),
11734 startLureRequest.TargetData[i].TargetID,
11735 this);
11736 }
11737 }
11496 return true; 11738 return true;
11497 } 11739 }
11498 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 11740 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11606,10 +11848,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11606 } 11848 }
11607 #endregion 11849 #endregion
11608 11850
11609 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11851 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
11610 if (handlerClassifiedGodDelete != null) 11852 if (handlerClassifiedGodDelete != null)
11611 handlerClassifiedGodDelete( 11853 handlerClassifiedGodDelete(
11612 classifiedGodDelete.Data.ClassifiedID, 11854 classifiedGodDelete.Data.ClassifiedID,
11855 classifiedGodDelete.Data.QueryID,
11613 this); 11856 this);
11614 return true; 11857 return true;
11615 } 11858 }
@@ -11912,6 +12155,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11912 /// <param name="simclient"></param> 12155 /// <param name="simclient"></param>
11913 /// <param name="packet"></param> 12156 /// <param name="packet"></param>
11914 /// <returns></returns> 12157 /// <returns></returns>
12158 // TODO: Convert old handler to use new method
12159/*
11915 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) 12160 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11916 { 12161 {
11917 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet; 12162 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
@@ -11919,6 +12164,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11919 12164
11920 if (cachedtex.AgentData.SessionID != SessionId) 12165 if (cachedtex.AgentData.SessionID != SessionId)
11921 return false; 12166 return false;
12167
11922 12168
11923 12169
11924 // TODO: don't create new blocks if recycling an old packet 12170 // TODO: don't create new blocks if recycling an old packet
@@ -11966,32 +12212,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11966 } 12212 }
11967 } 12213 }
11968 12214
11969 if (cacheItems != null) 12215 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
12216 if (handlerCachedTextureRequest != null)
11970 { 12217 {
11971 // We need to make sure the asset stored in the bake is available on this server also by its assetid before we map it to a Cacheid. 12218 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
11972 // Copy the baked textures to the sim's assets cache (local only). 12219 }
11973 foreach (WearableCacheItem item in cacheItems) 12220
11974 { 12221 return true;
11975 if (cache.GetCached(item.TextureID.ToString()) == null) 12222 }
11976 { 12223*/
11977 item.TextureAsset.Temporary = true; 12224
11978 item.TextureAsset.Local = true; 12225 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11979 cache.Store(item.TextureAsset); 12226 {
11980 } 12227 //m_log.Debug("texture cached: " + packet.ToString());
11981 } 12228 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
12229 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
12230
12231 if (cachedtex.AgentData.SessionID != SessionId)
12232 return false;
12233
12234 // TODO: don't create new blocks if recycling an old packet
12235 cachedresp.AgentData.AgentID = AgentId;
12236 cachedresp.AgentData.SessionID = m_sessionId;
12237 cachedresp.AgentData.SerialNum = cachedtex.AgentData.SerialNum;
12238 cachedresp.WearableData =
12239 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
12240
12241 int cacheHits = 0;
12242
12243 // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
12244
12245 WearableCacheItem[] cacheItems = null;
11982 12246
11983 // Return the cached textures 12247 ScenePresence p = m_scene.GetScenePresence(AgentId);
12248
12249 if (p != null && p.Appearance != null)
12250 {
12251 cacheItems = p.Appearance.WearableCacheItems;
12252 }
12253
12254 int maxWearablesLoop = cachedtex.WearableData.Length;
12255 if (maxWearablesLoop > cacheItems.Length)
12256 maxWearablesLoop = cacheItems.Length;
12257
12258 if (cacheItems != null)
12259 {
11984 for (int i = 0; i < maxWearablesLoop; i++) 12260 for (int i = 0; i < maxWearablesLoop; i++)
11985 { 12261 {
11986 WearableCacheItem item = 12262 int idx = cachedtex.WearableData[i].TextureIndex;
11987 WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex, cacheItems);
11988
11989 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 12263 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11990 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; 12264 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11991 cachedresp.WearableData[i].HostName = new byte[0]; 12265 cachedresp.WearableData[i].HostName = new byte[0];
11992 if (item != null && cachedtex.WearableData[i].ID == item.CacheId) 12266 if (cachedtex.WearableData[i].ID == cacheItems[idx].CacheId)
11993 { 12267 {
11994 cachedresp.WearableData[i].TextureID = item.TextureID; 12268 cachedresp.WearableData[i].TextureID = cacheItems[idx].TextureID;
12269 cacheHits++;
11995 } 12270 }
11996 else 12271 else
11997 { 12272 {
@@ -12001,7 +12276,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12001 } 12276 }
12002 else 12277 else
12003 { 12278 {
12004 // Cached textures not available
12005 for (int i = 0; i < maxWearablesLoop; i++) 12279 for (int i = 0; i < maxWearablesLoop; i++)
12006 { 12280 {
12007 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 12281 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
@@ -12010,13 +12284,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12010 cachedresp.WearableData[i].HostName = new byte[0]; 12284 cachedresp.WearableData[i].HostName = new byte[0];
12011 } 12285 }
12012 } 12286 }
12013 12287
12288 m_log.DebugFormat("texture cached: hits {0}", cacheHits);
12289
12014 cachedresp.Header.Zerocoded = true; 12290 cachedresp.Header.Zerocoded = true;
12015 OutPacket(cachedresp, ThrottleOutPacketType.Task); 12291 OutPacket(cachedresp, ThrottleOutPacketType.Task);
12016 12292
12017 return true; 12293 return true;
12018 } 12294 }
12019 12295
12020 /// <summary> 12296 /// <summary>
12021 /// Send a response back to a client when it asks the asset server (via the region server) if it has 12297 /// Send a response back to a client when it asks the asset server (via the region server) if it has
12022 /// its appearance texture cached. 12298 /// its appearance texture cached.
@@ -12080,209 +12356,147 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12080 } 12356 }
12081 else 12357 else
12082 { 12358 {
12083// m_log.DebugFormat( 12359 ClientChangeObject updatehandler = onClientChangeObject;
12084// "[CLIENT]: Processing block {0} type {1} for {2} {3}",
12085// i, block.Type, part.Name, part.LocalId);
12086 12360
12087// // Do this once since fetch parts creates a new array. 12361 if (updatehandler != null)
12088// SceneObjectPart[] parts = part.ParentGroup.Parts; 12362 {
12089// for (int j = 0; j < parts.Length; j++) 12363 ObjectChangeData udata = new ObjectChangeData();
12090// {
12091// part.StoreUndoState();
12092// parts[j].IgnoreUndoUpdate = true;
12093// }
12094 12364
12095 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 12365 /*ubit from ll JIRA:
12366 * 0x01 position
12367 * 0x02 rotation
12368 * 0x04 scale
12369
12370 * 0x08 LINK_SET
12371 * 0x10 UNIFORM for scale
12372 */
12096 12373
12097 switch (block.Type) 12374 // translate to internal changes
12098 { 12375 // not all cases .. just the ones older code did
12099 case 1:
12100 Vector3 pos1 = new Vector3(block.Data, 0);
12101 12376
12102 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12377 switch (block.Type)
12103 if (handlerUpdatePrimSinglePosition != null) 12378 {
12104 { 12379 case 1: //change position sp
12105 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 12380 udata.position = new Vector3(block.Data, 0);
12106 handlerUpdatePrimSinglePosition(localId, pos1, this);
12107 }
12108 break;
12109 12381
12110 case 2: 12382 udata.change = ObjectChangeType.primP;
12111 Quaternion rot1 = new Quaternion(block.Data, 0, true); 12383 updatehandler(localId, udata, this);
12384 break;
12112 12385
12113 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 12386 case 2: // rotation sp
12114 if (handlerUpdatePrimSingleRotation != null) 12387 udata.rotation = new Quaternion(block.Data, 0, true);
12115 {
12116 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
12117 handlerUpdatePrimSingleRotation(localId, rot1, this);
12118 }
12119 break;
12120 12388
12121 case 3: 12389 udata.change = ObjectChangeType.primR;
12122 Vector3 rotPos = new Vector3(block.Data, 0); 12390 updatehandler(localId, udata, this);
12123 Quaternion rot2 = new Quaternion(block.Data, 12, true); 12391 break;
12124 12392
12125 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 12393 case 3: // position plus rotation
12126 if (handlerUpdatePrimSingleRotationPosition != null) 12394 udata.position = new Vector3(block.Data, 0);
12127 { 12395 udata.rotation = new Quaternion(block.Data, 12, true);
12128 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
12129 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
12130 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
12131 }
12132 break;
12133 12396
12134 case 4: 12397 udata.change = ObjectChangeType.primPR;
12135 case 20: 12398 updatehandler(localId, udata, this);
12136 Vector3 scale4 = new Vector3(block.Data, 0); 12399 break;
12137 12400
12138 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 12401 case 4: // scale sp
12139 if (handlerUpdatePrimScale != null) 12402 udata.scale = new Vector3(block.Data, 0);
12140 { 12403 udata.change = ObjectChangeType.primS;
12141 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
12142 handlerUpdatePrimScale(localId, scale4, this);
12143 }
12144 break;
12145 12404
12146 case 5: 12405 updatehandler(localId, udata, this);
12147 Vector3 scale1 = new Vector3(block.Data, 12); 12406 break;
12148 Vector3 pos11 = new Vector3(block.Data, 0);
12149 12407
12150 handlerUpdatePrimScale = OnUpdatePrimScale; 12408 case 0x14: // uniform scale sp
12151 if (handlerUpdatePrimScale != null) 12409 udata.scale = new Vector3(block.Data, 0);
12152 {
12153 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12154 handlerUpdatePrimScale(localId, scale1, this);
12155 12410
12156 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12411 udata.change = ObjectChangeType.primUS;
12157 if (handlerUpdatePrimSinglePosition != null) 12412 updatehandler(localId, udata, this);
12158 { 12413 break;
12159 handlerUpdatePrimSinglePosition(localId, pos11, this);
12160 }
12161 }
12162 break;
12163 12414
12164 case 9: 12415 case 5: // scale and position sp
12165 Vector3 pos2 = new Vector3(block.Data, 0); 12416 udata.position = new Vector3(block.Data, 0);
12417 udata.scale = new Vector3(block.Data, 12);
12166 12418
12167 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 12419 udata.change = ObjectChangeType.primPS;
12420 updatehandler(localId, udata, this);
12421 break;
12168 12422
12169 if (handlerUpdateVector != null) 12423 case 0x15: //uniform scale and position
12170 { 12424 udata.position = new Vector3(block.Data, 0);
12171 handlerUpdateVector(localId, pos2, this); 12425 udata.scale = new Vector3(block.Data, 12);
12172 }
12173 break;
12174 12426
12175 case 10: 12427 udata.change = ObjectChangeType.primPUS;
12176 Quaternion rot3 = new Quaternion(block.Data, 0, true); 12428 updatehandler(localId, udata, this);
12429 break;
12177 12430
12178 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 12431 // now group related (bit 4)
12179 if (handlerUpdatePrimRotation != null) 12432 case 9: //( 8 + 1 )group position
12180 { 12433 udata.position = new Vector3(block.Data, 0);
12181 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
12182 handlerUpdatePrimRotation(localId, rot3, this);
12183 }
12184 break;
12185 12434
12186 case 11: 12435 udata.change = ObjectChangeType.groupP;
12187 Vector3 pos3 = new Vector3(block.Data, 0); 12436 updatehandler(localId, udata, this);
12188 Quaternion rot4 = new Quaternion(block.Data, 12, true); 12437 break;
12189 12438
12190 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 12439 case 0x0A: // (8 + 2) group rotation
12191 if (handlerUpdatePrimGroupRotation != null) 12440 udata.rotation = new Quaternion(block.Data, 0, true);
12192 {
12193 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
12194 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
12195 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
12196 }
12197 break;
12198 case 12:
12199 case 28:
12200 Vector3 scale7 = new Vector3(block.Data, 0);
12201 12441
12202 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 12442 udata.change = ObjectChangeType.groupR;
12203 if (handlerUpdatePrimGroupScale != null) 12443 updatehandler(localId, udata, this);
12204 { 12444 break;
12205 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
12206 handlerUpdatePrimGroupScale(localId, scale7, this);
12207 }
12208 break;
12209 12445
12210 case 13: 12446 case 0x0B: //( 8 + 2 + 1) group rotation and position
12211 Vector3 scale2 = new Vector3(block.Data, 12); 12447 udata.position = new Vector3(block.Data, 0);
12212 Vector3 pos4 = new Vector3(block.Data, 0); 12448 udata.rotation = new Quaternion(block.Data, 12, true);
12213 12449
12214 handlerUpdatePrimScale = OnUpdatePrimScale; 12450 udata.change = ObjectChangeType.groupPR;
12215 if (handlerUpdatePrimScale != null) 12451 updatehandler(localId, udata, this);
12216 { 12452 break;
12217 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12218 handlerUpdatePrimScale(localId, scale2, this);
12219 12453
12220 // Change the position based on scale (for bug number 246) 12454 case 0x0C: // (8 + 4) group scale
12221 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12455 // only afects root prim and only sent by viewer editor object tab scaling
12222 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 12456 // mouse edition only allows uniform scaling
12223 if (handlerUpdatePrimSinglePosition != null) 12457 // SL MAY CHANGE THIS in viewers
12224 {
12225 handlerUpdatePrimSinglePosition(localId, pos4, this);
12226 }
12227 }
12228 break;
12229 12458
12230 case 29: 12459 udata.scale = new Vector3(block.Data, 0);
12231 Vector3 scale5 = new Vector3(block.Data, 12);
12232 Vector3 pos5 = new Vector3(block.Data, 0);
12233 12460
12234 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 12461 udata.change = ObjectChangeType.groupS;
12235 if (handlerUpdatePrimGroupScale != null) 12462 updatehandler(localId, udata, this);
12236 {
12237 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
12238 part.StoreUndoState(true);
12239 part.IgnoreUndoUpdate = true;
12240 handlerUpdatePrimGroupScale(localId, scale5, this);
12241 handlerUpdateVector = OnUpdatePrimGroupPosition;
12242 12463
12243 if (handlerUpdateVector != null) 12464 break;
12244 {
12245 handlerUpdateVector(localId, pos5, this);
12246 }
12247 12465
12248 part.IgnoreUndoUpdate = false; 12466 case 0x0D: //(8 + 4 + 1) group scale and position
12249 } 12467 // exception as above
12250 12468
12251 break; 12469 udata.position = new Vector3(block.Data, 0);
12470 udata.scale = new Vector3(block.Data, 12);
12252 12471
12253 case 21: 12472 udata.change = ObjectChangeType.groupPS;
12254 Vector3 scale6 = new Vector3(block.Data, 12); 12473 updatehandler(localId, udata, this);
12255 Vector3 pos6 = new Vector3(block.Data, 0); 12474 break;
12256 12475
12257 handlerUpdatePrimScale = OnUpdatePrimScale; 12476 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
12258 if (handlerUpdatePrimScale != null) 12477 udata.scale = new Vector3(block.Data, 0);
12259 {
12260 part.StoreUndoState(false);
12261 part.IgnoreUndoUpdate = true;
12262 12478
12263 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 12479 udata.change = ObjectChangeType.groupUS;
12264 handlerUpdatePrimScale(localId, scale6, this); 12480 updatehandler(localId, udata, this);
12265 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 12481 break;
12266 if (handlerUpdatePrimSinglePosition != null)
12267 {
12268 handlerUpdatePrimSinglePosition(localId, pos6, this);
12269 }
12270 12482
12271 part.IgnoreUndoUpdate = false; 12483 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
12272 } 12484 udata.position = new Vector3(block.Data, 0);
12273 break; 12485 udata.scale = new Vector3(block.Data, 12);
12274 12486
12275 default: 12487 udata.change = ObjectChangeType.groupPUS;
12276 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); 12488 updatehandler(localId, udata, this);
12277 break; 12489 break;
12490
12491 default:
12492 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
12493 break;
12494 }
12278 } 12495 }
12279 12496
12280// for (int j = 0; j < parts.Length; j++)
12281// parts[j].IgnoreUndoUpdate = false;
12282 } 12497 }
12283 } 12498 }
12284 } 12499 }
12285
12286 return true; 12500 return true;
12287 } 12501 }
12288 12502
@@ -12342,7 +12556,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12342 /// <param name="throttles"></param> 12556 /// <param name="throttles"></param>
12343 public void SetChildAgentThrottle(byte[] throttles) 12557 public void SetChildAgentThrottle(byte[] throttles)
12344 { 12558 {
12345 m_udpClient.SetThrottles(throttles); 12559 SetChildAgentThrottle(throttles, 1.0f);
12560 }
12561
12562 public void SetChildAgentThrottle(byte[] throttles,float factor)
12563 {
12564 m_udpClient.SetThrottles(throttles, factor);
12565 GenericCall2 handler = OnUpdateThrottles;
12566 if (handler != null)
12567 {
12568 handler();
12569 }
12570 }
12571
12572 /// <summary>
12573 /// Sets the throttles from values supplied caller
12574 /// </summary>
12575 /// <param name="throttles"></param>
12576 public void SetAgentThrottleSilent(int throttle, int setting)
12577 {
12578 m_udpClient.ForceThrottleSetting(throttle,setting);
12579 }
12580
12581 public int GetAgentThrottleSilent(int throttle)
12582 {
12583 return m_udpClient.GetThrottleSetting(throttle);
12346 } 12584 }
12347 12585
12348 /// <summary> 12586 /// <summary>
@@ -12450,8 +12688,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12450 uint regionY = 0; 12688 uint regionY = 0;
12451 12689
12452 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY); 12690 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY);
12453 locx = Convert.ToSingle(args[0]) - (float)regionX; 12691 locx = (float)(Convert.ToDouble(args[0]) - (double)regionX);
12454 locy = Convert.ToSingle(args[1]) - (float)regionY; 12692 locy = (float)(Convert.ToDouble(args[1]) - (double)regionY);
12455 locz = Convert.ToSingle(args[2]); 12693 locz = Convert.ToSingle(args[2]);
12456 12694
12457 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo; 12695 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo;
@@ -12736,7 +12974,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12736// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", 12974// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12737// requestID, taskID, (SourceType)sourceType, Name); 12975// requestID, taskID, (SourceType)sourceType, Name);
12738 12976
12977
12978 //Note, the bool returned from the below function is useless since it is always false.
12739 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12979 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12980
12740 } 12981 }
12741 12982
12742 /// <summary> 12983 /// <summary>
@@ -12819,7 +13060,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12819 /// <returns></returns> 13060 /// <returns></returns>
12820 private static int CalculateNumPackets(byte[] data) 13061 private static int CalculateNumPackets(byte[] data)
12821 { 13062 {
12822 const uint m_maxPacketSize = 600; 13063// const uint m_maxPacketSize = 600;
13064 uint m_maxPacketSize = MaxTransferBytesPerPacket;
12823 int numPackets = 1; 13065 int numPackets = 1;
12824 13066
12825 if (data == null) 13067 if (data == null)
@@ -12930,7 +13172,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12930 // this is the username of the *owner* 13172 // this is the username of the *owner*
12931 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName); 13173 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
12932 dialog.Data.LastName = Util.StringToBytes256(ownerLastName); 13174 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
12933 dialog.Data.Message = Util.StringToBytes256(message); 13175 dialog.Data.Message = Util.StringToBytes(message,512);
12934 13176
12935 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1]; 13177 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[1];
12936 buttons[0] = new ScriptDialogPacket.ButtonsBlock(); 13178 buttons[0] = new ScriptDialogPacket.ButtonsBlock();
@@ -12962,8 +13204,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12962 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = 13204 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12963 CreateImprovedTerseBlock(p, false); 13205 CreateImprovedTerseBlock(p, false);
12964 13206
12965 const float TIME_DILATION = 1.0f; 13207// const float TIME_DILATION = 1.0f;
12966 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 13208 ushort timeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);;
12967 13209
12968 ImprovedTerseObjectUpdatePacket packet 13210 ImprovedTerseObjectUpdatePacket packet
12969 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 13211 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 0394e54..36e0a0e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -96,9 +96,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
96 set 96 set
97 { 97 {
98 m_throttleDebugLevel = value; 98 m_throttleDebugLevel = value;
99/*
99 m_throttleClient.DebugLevel = m_throttleDebugLevel; 100 m_throttleClient.DebugLevel = m_throttleDebugLevel;
100 foreach (TokenBucket tb in m_throttleCategories) 101 foreach (TokenBucket tb in m_throttleCategories)
101 tb.DebugLevel = m_throttleDebugLevel; 102 tb.DebugLevel = m_throttleDebugLevel;
103 */
102 } 104 }
103 } 105 }
104 private int m_throttleDebugLevel; 106 private int m_throttleDebugLevel;
@@ -120,16 +122,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
120 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary> 122 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
121 public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200); 123 public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
122 124
123 /// <summary>
124 /// If true then we take action in response to unacked reliably sent packets such as resending the packet.
125 /// </summary>
126 public bool ProcessUnackedSends { get; set; }
127
128 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 125 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
129 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 126 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
130 127
131 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> 128 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
132 public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>(); 129 public readonly DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>();
133 130
134 /// <summary>Current packet sequence number</summary> 131 /// <summary>Current packet sequence number</summary>
135 public int CurrentSequence; 132 public int CurrentSequence;
@@ -181,7 +178,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 /// <summary>Throttle buckets for each packet category</summary> 178 /// <summary>Throttle buckets for each packet category</summary>
182 private readonly TokenBucket[] m_throttleCategories; 179 private readonly TokenBucket[] m_throttleCategories;
183 /// <summary>Outgoing queues for throttled packets</summary> 180 /// <summary>Outgoing queues for throttled packets</summary>
184 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 181 private readonly DoubleLocklessQueue<OutgoingPacket>[] m_packetOutboxes = new DoubleLocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
185 /// <summary>A container that can hold one packet for each outbox, used to store 182 /// <summary>A container that can hold one packet for each outbox, used to store
186 /// dequeued packets that are being held for throttling</summary> 183 /// dequeued packets that are being held for throttling</summary>
187 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; 184 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
@@ -193,6 +190,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 190
194 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 191 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
195 private int m_maxRTO = 60000; 192 private int m_maxRTO = 60000;
193 public bool m_deliverPackets = true;
194
195 private float m_burstTime;
196
197 public int m_lastStartpingTimeMS;
198 public int m_pingMS;
199
200 public int PingTimeMS
201 {
202 get
203 {
204 if (m_pingMS < 10)
205 return 10;
206 if(m_pingMS > 2000)
207 return 2000;
208 return m_pingMS;
209 }
210 }
196 211
197 /// <summary> 212 /// <summary>
198 /// This is the percentage of the udp texture queue to add to the task queue since 213 /// This is the percentage of the udp texture queue to add to the task queue since
@@ -232,31 +247,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
232 if (maxRTO != 0) 247 if (maxRTO != 0)
233 m_maxRTO = maxRTO; 248 m_maxRTO = maxRTO;
234 249
235 ProcessUnackedSends = true; 250 m_burstTime = rates.BrustTime;
251 float m_burst = rates.ClientMaxRate * m_burstTime;
236 252
237 // Create a token bucket throttle for this client that has the scene token bucket as a parent 253 // Create a token bucket throttle for this client that has the scene token bucket as a parent
238 m_throttleClient 254 m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.ClientMaxRate, m_burst, rates.AdaptiveThrottlesEnabled);
239 = new AdaptiveTokenBucket(
240 string.Format("adaptive throttle for {0} in {1}", AgentID, server.Scene.Name),
241 parentThrottle, 0, rates.Total, rates.MinimumAdaptiveThrottleRate, rates.AdaptiveThrottlesEnabled);
242 255
243 // Create an array of token buckets for this clients different throttle categories 256 // Create an array of token buckets for this clients different throttle categories
244 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 257 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
245 258
246 m_cannibalrate = rates.CannibalizeTextureRate; 259 m_cannibalrate = rates.CannibalizeTextureRate;
247 260
261 m_burst = rates.Total * rates.BrustTime;
262
248 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 263 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
249 { 264 {
250 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 265 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
251 266
252 // Initialize the packet outboxes, where packets sit while they are waiting for tokens 267 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
253 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 268 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
254
255 // Initialize the token buckets that control the throttling for each category 269 // Initialize the token buckets that control the throttling for each category
256 m_throttleCategories[i] 270 m_throttleCategories[i] = new TokenBucket(m_throttleClient, rates.GetRate(type), m_burst);
257 = new TokenBucket(
258 string.Format("{0} throttle for {1} in {2}", type, AgentID, server.Scene.Name),
259 m_throttleClient, rates.GetRate(type), 0);
260 } 271 }
261 272
262 // Default the retransmission timeout to one second 273 // Default the retransmission timeout to one second
@@ -264,6 +275,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
264 275
265 // Initialize this to a sane value to prevent early disconnects 276 // Initialize this to a sane value to prevent early disconnects
266 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue; 277 TickLastPacketReceived = Environment.TickCount & Int32.MaxValue;
278 m_pingMS = (int)(3.0 * server.TickCountResolution); // so filter doesnt start at 0;
267 } 279 }
268 280
269 /// <summary> 281 /// <summary>
@@ -302,9 +314,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
302 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 314 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
303 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 315 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
304 m_info.totalThrottle = (int)m_throttleClient.DripRate; 316 m_info.totalThrottle = (int)m_throttleClient.DripRate;
305 m_info.targetThrottle = (int)m_throttleClient.TargetDripRate;
306 m_info.maxThrottle = (int)m_throttleClient.MaxDripRate;
307
308 return m_info; 317 return m_info;
309 } 318 }
310 319
@@ -341,8 +350,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
341 /// <param name="throttleType"></param> 350 /// <param name="throttleType"></param>
342 public int GetPacketsQueuedCount(ThrottleOutPacketType throttleType) 351 public int GetPacketsQueuedCount(ThrottleOutPacketType throttleType)
343 { 352 {
344 if ((int)throttleType > 0) 353 int icat = (int)throttleType;
345 return m_packetOutboxes[(int)throttleType].Count; 354 if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT)
355 return m_packetOutboxes[icat].Count;
346 else 356 else
347 return 0; 357 return 0;
348 } 358 }
@@ -389,6 +399,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
389 399
390 public void SetThrottles(byte[] throttleData) 400 public void SetThrottles(byte[] throttleData)
391 { 401 {
402 SetThrottles(throttleData, 1.0f);
403 }
404
405 public void SetThrottles(byte[] throttleData, float factor)
406 {
392 byte[] adjData; 407 byte[] adjData;
393 int pos = 0; 408 int pos = 0;
394 409
@@ -408,24 +423,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
408 } 423 }
409 424
410 // 0.125f converts from bits to bytes 425 // 0.125f converts from bits to bytes
411 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 426 float scale = 0.125f * factor;
412 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 427 int resend = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
413 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 428 int land = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
414 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 429 int wind = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
415 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 430 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
416 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; 431 int task = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
417 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); 432 int texture = (int)(BitConverter.ToSingle(adjData, pos) * scale); pos += 4;
433 int asset = (int)(BitConverter.ToSingle(adjData, pos) * scale);
434
418 435
419 if (ThrottleDebugLevel > 0)
420 {
421 long total = resend + land + wind + cloud + task + texture + asset;
422 m_log.DebugFormat(
423 "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}",
424 AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total);
425 }
426 436
427 // Make sure none of the throttles are set below our packet MTU, 437 // Make sure none of the throttles are set below our packet MTU,
428 // otherwise a throttle could become permanently clogged 438 // otherwise a throttle could become permanently clogged
439
440/* now using floats
429 resend = Math.Max(resend, LLUDPServer.MTU); 441 resend = Math.Max(resend, LLUDPServer.MTU);
430 land = Math.Max(land, LLUDPServer.MTU); 442 land = Math.Max(land, LLUDPServer.MTU);
431 wind = Math.Max(wind, LLUDPServer.MTU); 443 wind = Math.Max(wind, LLUDPServer.MTU);
@@ -433,52 +445,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP
433 task = Math.Max(task, LLUDPServer.MTU); 445 task = Math.Max(task, LLUDPServer.MTU);
434 texture = Math.Max(texture, LLUDPServer.MTU); 446 texture = Math.Max(texture, LLUDPServer.MTU);
435 asset = Math.Max(asset, LLUDPServer.MTU); 447 asset = Math.Max(asset, LLUDPServer.MTU);
448*/
436 449
437 // Since most textures are now delivered through http, make it possible 450 // Since most textures are now delivered through http, make it possible
438 // to cannibalize some of the bw from the texture throttle to use for 451 // to cannibalize some of the bw from the texture throttle to use for
439 // the task queue (e.g. object updates) 452 // the task queue (e.g. object updates)
440 task = task + (int)(m_cannibalrate * texture); 453 task = task + (int)(m_cannibalrate * texture);
441 texture = (int)((1 - m_cannibalrate) * texture); 454 texture = (int)((1 - m_cannibalrate) * texture);
442 455
443 //int total = resend + land + wind + cloud + task + texture + asset; 456 int total = resend + land + wind + cloud + task + texture + asset;
457
458 float m_burst = total * m_burstTime;
444 459
445 if (ThrottleDebugLevel > 0) 460 if (ThrottleDebugLevel > 0)
446 { 461 {
447 long total = resend + land + wind + cloud + task + texture + asset;
448 m_log.DebugFormat( 462 m_log.DebugFormat(
449 "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}", 463 "[LLUDPCLIENT]: {0} is setting throttles in {1} to Resend={2}, Land={3}, Wind={4}, Cloud={5}, Task={6}, Texture={7}, Asset={8}, TOTAL = {9}",
450 AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total); 464 AgentID, m_udpServer.Scene.Name, resend, land, wind, cloud, task, texture, asset, total);
451 } 465 }
452 466
453 // Update the token buckets with new throttle values
454 if (m_throttleClient.AdaptiveEnabled)
455 {
456 long total = resend + land + wind + cloud + task + texture + asset;
457 m_throttleClient.TargetDripRate = total;
458 }
459
460 TokenBucket bucket; 467 TokenBucket bucket;
461 468
462 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend]; 469 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
463 bucket.RequestedDripRate = resend; 470 bucket.RequestedDripRate = resend;
471 bucket.RequestedBurst = m_burst;
464 472
465 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land]; 473 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
466 bucket.RequestedDripRate = land; 474 bucket.RequestedDripRate = land;
475 bucket.RequestedBurst = m_burst;
467 476
468 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind]; 477 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
469 bucket.RequestedDripRate = wind; 478 bucket.RequestedDripRate = wind;
479 bucket.RequestedBurst = m_burst;
470 480
471 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud]; 481 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
472 bucket.RequestedDripRate = cloud; 482 bucket.RequestedDripRate = cloud;
483 bucket.RequestedBurst = m_burst;
473 484
474 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset]; 485 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
475 bucket.RequestedDripRate = asset; 486 bucket.RequestedDripRate = asset;
487 bucket.RequestedBurst = m_burst;
476 488
477 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task]; 489 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
478 bucket.RequestedDripRate = task; 490 bucket.RequestedDripRate = task;
491 bucket.RequestedBurst = m_burst;
479 492
480 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; 493 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
481 bucket.RequestedDripRate = texture; 494 bucket.RequestedDripRate = texture;
495 bucket.RequestedBurst = m_burst;
482 496
483 // Reset the packed throttles cached data 497 // Reset the packed throttles cached data
484 m_packedThrottles = null; 498 m_packedThrottles = null;
@@ -496,25 +510,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
496 int i = 0; 510 int i = 0;
497 511
498 // multiply by 8 to convert bytes back to bits 512 // multiply by 8 to convert bytes back to bits
499 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier; 513 multiplier *= 8;
514
515 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * multiplier;
500 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 516 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
501 517
502 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier; 518 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * multiplier;
503 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 519 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
504 520
505 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier; 521 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * multiplier;
506 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 522 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
507 523
508 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier; 524 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * multiplier;
509 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 525 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
510 526
511 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier; 527 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * multiplier;
512 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 528 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
513 529
514 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier; 530 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * multiplier;
515 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 531 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
516 532
517 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier; 533 rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * multiplier;
518 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4; 534 Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
519 535
520 m_packedThrottles = data; 536 m_packedThrottles = data;
@@ -522,6 +538,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
522 538
523 return data; 539 return data;
524 } 540 }
541
542 public int GetCatBytesCanSend(ThrottleOutPacketType cat, int timeMS)
543 {
544 int icat = (int)cat;
545 if (icat > 0 && icat < THROTTLE_CATEGORY_COUNT)
546 {
547 TokenBucket bucket = m_throttleCategories[icat];
548 return bucket.GetCatBytesCanSend(timeMS);
549 }
550 else
551 return 0;
552 }
525 553
526 /// <summary> 554 /// <summary>
527 /// Queue an outgoing packet if appropriate. 555 /// Queue an outgoing packet if appropriate.
@@ -534,32 +562,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
534 /// </returns> 562 /// </returns>
535 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) 563 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
536 { 564 {
565 return EnqueueOutgoing(packet, forceQueue, false);
566 }
567
568 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority)
569 {
537 int category = (int)packet.Category; 570 int category = (int)packet.Category;
538 571
539 if (category >= 0 && category < m_packetOutboxes.Length) 572 if (category >= 0 && category < m_packetOutboxes.Length)
540 { 573 {
541 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 574 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
575
576 if (m_deliverPackets == false)
577 {
578 queue.Enqueue(packet, highPriority);
579 return true;
580 }
581
542 TokenBucket bucket = m_throttleCategories[category]; 582 TokenBucket bucket = m_throttleCategories[category];
543 583
544 // Don't send this packet if there is already a packet waiting in the queue 584 // Don't send this packet if queue is not empty
545 // even if we have the tokens to send it, tokens should go to the already 585 if (queue.Count > 0 || m_nextPackets[category] != null)
546 // queued packets
547 if (queue.Count > 0)
548 { 586 {
549 queue.Enqueue(packet); 587 queue.Enqueue(packet, highPriority);
550 return true; 588 return true;
551 } 589 }
552 590
553 591 if (!forceQueue && bucket.CheckTokens(packet.Buffer.DataLength))
554 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
555 { 592 {
556 // Enough tokens were removed from the bucket, the packet will not be queued 593 // enough tokens so it can be sent imediatly by caller
594 bucket.RemoveTokens(packet.Buffer.DataLength);
557 return false; 595 return false;
558 } 596 }
559 else 597 else
560 { 598 {
561 // Force queue specified or not enough tokens in the bucket, queue this packet 599 // Force queue specified or not enough tokens in the bucket, queue this packet
562 queue.Enqueue(packet); 600 queue.Enqueue(packet, highPriority);
563 return true; 601 return true;
564 } 602 }
565 } 603 }
@@ -568,6 +606,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
568 // We don't have a token bucket for this category, so it will not be queued 606 // We don't have a token bucket for this category, so it will not be queued
569 return false; 607 return false;
570 } 608 }
609
571 } 610 }
572 611
573 /// <summary> 612 /// <summary>
@@ -588,8 +627,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
588 /// <returns>True if any packets were sent, otherwise false</returns> 627 /// <returns>True if any packets were sent, otherwise false</returns>
589 public bool DequeueOutgoing() 628 public bool DequeueOutgoing()
590 { 629 {
591 OutgoingPacket packet; 630// if (m_deliverPackets == false) return false;
592 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 631
632 OutgoingPacket packet = null;
633 DoubleLocklessQueue<OutgoingPacket> queue;
593 TokenBucket bucket; 634 TokenBucket bucket;
594 bool packetSent = false; 635 bool packetSent = false;
595 ThrottleOutPacketTypeFlags emptyCategories = 0; 636 ThrottleOutPacketTypeFlags emptyCategories = 0;
@@ -613,6 +654,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
613 m_udpServer.SendPacketFinal(nextPacket); 654 m_udpServer.SendPacketFinal(nextPacket);
614 m_nextPackets[i] = null; 655 m_nextPackets[i] = null;
615 packetSent = true; 656 packetSent = true;
657
658 if (m_packetOutboxes[i].Count < 5)
659 emptyCategories |= CategoryToFlag(i);
616 } 660 }
617 } 661 }
618 else 662 else
@@ -620,32 +664,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP
620 // No dequeued packet waiting to be sent, try to pull one off 664 // No dequeued packet waiting to be sent, try to pull one off
621 // this queue 665 // this queue
622 queue = m_packetOutboxes[i]; 666 queue = m_packetOutboxes[i];
623 if (queue.Dequeue(out packet)) 667 if (queue != null)
624 { 668 {
625 // A packet was pulled off the queue. See if we have 669 bool success = false;
626 // enough tokens in the bucket to send it out 670 try
627 if (bucket.RemoveTokens(packet.Buffer.DataLength))
628 { 671 {
629 // Send the packet 672 success = queue.Dequeue(out packet);
630 m_udpServer.SendPacketFinal(packet);
631 packetSent = true;
632 } 673 }
633 else 674 catch
634 { 675 {
635 // Save the dequeued packet for the next iteration 676 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
636 m_nextPackets[i] = packet;
637 } 677 }
678 if (success)
679 {
680 // A packet was pulled off the queue. See if we have
681 // enough tokens in the bucket to send it out
682 if (bucket.RemoveTokens(packet.Buffer.DataLength))
683 {
684 // Send the packet
685 m_udpServer.SendPacketFinal(packet);
686 packetSent = true;
687
688 if (queue.Count < 5)
689 emptyCategories |= CategoryToFlag(i);
690 }
691 else
692 {
693 // Save the dequeued packet for the next iteration
694 m_nextPackets[i] = packet;
695 }
638 696
639 // If the queue is empty after this dequeue, fire the queue 697 }
640 // empty callback now so it has a chance to fill before we 698 else
641 // get back here 699 {
642 if (queue.Count == 0) 700 // No packets in this queue. Fire the queue empty callback
701 // if it has not been called recently
643 emptyCategories |= CategoryToFlag(i); 702 emptyCategories |= CategoryToFlag(i);
703 }
644 } 704 }
645 else 705 else
646 { 706 {
647 // No packets in this queue. Fire the queue empty callback 707 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
648 // if it has not been called recently
649 emptyCategories |= CategoryToFlag(i); 708 emptyCategories |= CategoryToFlag(i);
650 } 709 }
651 } 710 }
@@ -712,6 +771,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
712 RTO = Math.Min(RTO * 2, m_maxRTO); 771 RTO = Math.Min(RTO * 2, m_maxRTO);
713 } 772 }
714 773
774
775 const int MIN_CALLBACK_MS = 10;
776
715 /// <summary> 777 /// <summary>
716 /// Does an early check to see if this queue empty callback is already 778 /// Does an early check to see if this queue empty callback is already
717 /// running, then asynchronously firing the event 779 /// running, then asynchronously firing the event
@@ -719,24 +781,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
719 /// <param name="categories">Throttle categories to fire the callback for</param> 781 /// <param name="categories">Throttle categories to fire the callback for</param>
720 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) 782 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
721 { 783 {
722// if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) 784 if (!m_isQueueEmptyRunning)
723 if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
724 { 785 {
725 m_isQueueEmptyRunning = true;
726
727 int start = Environment.TickCount & Int32.MaxValue; 786 int start = Environment.TickCount & Int32.MaxValue;
728 const int MIN_CALLBACK_MS = 30; 787
788 if (start < m_nextOnQueueEmpty)
789 return;
790
791 m_isQueueEmptyRunning = true;
729 792
730 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 793 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
731 if (m_nextOnQueueEmpty == 0) 794 if (m_nextOnQueueEmpty == 0)
732 m_nextOnQueueEmpty = 1; 795 m_nextOnQueueEmpty = 1;
733 796
734 // Use a value of 0 to signal that FireQueueEmpty is running 797 if (HasUpdates(categories))
735// m_nextOnQueueEmpty = 0;
736
737 m_categories = categories;
738
739 if (HasUpdates(m_categories))
740 { 798 {
741 if (!m_udpServer.OqrEngine.IsRunning) 799 if (!m_udpServer.OqrEngine.IsRunning)
742 { 800 {
@@ -756,7 +814,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
756 } 814 }
757 815
758 private bool m_isQueueEmptyRunning; 816 private bool m_isQueueEmptyRunning;
759 private ThrottleOutPacketTypeFlags m_categories = 0; 817
760 818
761 /// <summary> 819 /// <summary>
762 /// Fires the OnQueueEmpty callback and sets the minimum time that it 820 /// Fires the OnQueueEmpty callback and sets the minimum time that it
@@ -767,33 +825,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
767 /// signature</param> 825 /// signature</param>
768 public void FireQueueEmpty(object o) 826 public void FireQueueEmpty(object o)
769 { 827 {
770// m_log.DebugFormat("[LLUDPCLIENT]: FireQueueEmpty for {0} in {1}", AgentID, m_udpServer.Scene.Name); 828 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
771 829 QueueEmpty callback = OnQueueEmpty;
772// int start = Environment.TickCount & Int32.MaxValue;
773// const int MIN_CALLBACK_MS = 30;
774 830
775// if (m_udpServer.IsRunningOutbound) 831 if (callback != null)
776// { 832 {
777 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; 833 // if (m_udpServer.IsRunningOutbound)
778 QueueEmpty callback = OnQueueEmpty; 834 // {
779 835 try { callback(categories); }
780 if (callback != null) 836 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
781 { 837 // }
782// if (m_udpServer.IsRunningOutbound) 838 }
783// {
784 try { callback(categories); }
785 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
786// }
787 }
788// }
789 839
790// m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 840 m_isQueueEmptyRunning = false;
791// if (m_nextOnQueueEmpty == 0) 841 }
792// m_nextOnQueueEmpty = 1;
793 842
794// } 843 internal void ForceThrottleSetting(int throttle, int setting)
844 {
845 if (throttle > 0 && throttle < THROTTLE_CATEGORY_COUNT)
846 m_throttleCategories[throttle].RequestedDripRate = Math.Max(setting, LLUDPServer.MTU);
847 }
795 848
796 m_isQueueEmptyRunning = false; 849 internal int GetThrottleSetting(int throttle)
850 {
851 if (throttle > 0 && throttle < THROTTLE_CATEGORY_COUNT)
852 return (int)m_throttleCategories[throttle].RequestedDripRate;
853 else
854 return 0;
797 } 855 }
798 856
799 /// <summary> 857 /// <summary>
@@ -839,4 +897,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
839 } 897 }
840 } 898 }
841 } 899 }
900
901 public class DoubleLocklessQueue<T> : OpenSim.Framework.LocklessQueue<T>
902 {
903 OpenSim.Framework.LocklessQueue<T> highQueue = new OpenSim.Framework.LocklessQueue<T>();
904
905 public override int Count
906 {
907 get
908 {
909 return base.Count + highQueue.Count;
910 }
911 }
912
913 public override bool Dequeue(out T item)
914 {
915 if (highQueue.Dequeue(out item))
916 return true;
917
918 return base.Dequeue(out item);
919 }
920
921 public void Enqueue(T item, bool highPriority)
922 {
923 if (highPriority)
924 highQueue.Enqueue(item);
925 else
926 Enqueue(item);
927 }
928 }
842} 929}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 4528714..8f345e7 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -284,7 +284,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
284 /// <summary>Handlers for incoming packets</summary> 284 /// <summary>Handlers for incoming packets</summary>
285 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 285 //PacketEventDictionary packetEvents = new PacketEventDictionary();
286 /// <summary>Incoming packets that are awaiting handling</summary> 286 /// <summary>Incoming packets that are awaiting handling</summary>
287 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 287 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
288
289 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
288 290
289 /// <summary>Bandwidth throttle for this UDP server</summary> 291 /// <summary>Bandwidth throttle for this UDP server</summary>
290 public TokenBucket Throttle { get; private set; } 292 public TokenBucket Throttle { get; private set; }
@@ -342,14 +344,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
342 /// <summary>Flag to signal when clients should send pings</summary> 344 /// <summary>Flag to signal when clients should send pings</summary>
343 protected bool m_sendPing; 345 protected bool m_sendPing;
344 346
347 private int m_animationSequenceNumber;
348
349 public int NextAnimationSequenceNumber
350 {
351 get
352 {
353 m_animationSequenceNumber++;
354 if (m_animationSequenceNumber > 2147482624)
355 m_animationSequenceNumber = 1;
356 return m_animationSequenceNumber;
357 }
358 }
359
360
361
362 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
363
345 /// <summary> 364 /// <summary>
346 /// Event used to signal when queued packets are available for sending. 365 /// Event used to signal when queued packets are available for sending.
347 /// </summary> 366 /// </summary>
348 /// <remarks> 367 /// <remarks>
349 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling. 368 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling.
350 /// Some data is sent immediately and not queued. That data would not trigger this event. 369 /// Some data is sent immediately and not queued. That data would not trigger this event.
370 /// WRONG use. May be usefull in future revision
351 /// </remarks> 371 /// </remarks>
352 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false); 372// private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
353 373
354 private Pool<IncomingPacket> m_incomingPacketPool; 374 private Pool<IncomingPacket> m_incomingPacketPool;
355 375
@@ -431,16 +451,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
431 451
432 // Measure the resolution of Environment.TickCount 452 // Measure the resolution of Environment.TickCount
433 TickCountResolution = 0f; 453 TickCountResolution = 0f;
434 for (int i = 0; i < 5; i++) 454 for (int i = 0; i < 10; i++)
435 { 455 {
436 int start = Environment.TickCount; 456 int start = Environment.TickCount;
437 int now = start; 457 int now = start;
438 while (now == start) 458 while (now == start)
439 now = Environment.TickCount; 459 now = Environment.TickCount;
440 TickCountResolution += (float)(now - start) * 0.2f; 460 TickCountResolution += (float)(now - start) * 0.1f;
441 } 461 }
442 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
443 TickCountResolution = (float)Math.Ceiling(TickCountResolution); 462 TickCountResolution = (float)Math.Ceiling(TickCountResolution);
463 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
444 464
445 #endregion Environment.TickCount Measurement 465 #endregion Environment.TickCount Measurement
446 466
@@ -448,6 +468,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
448 int sceneThrottleBps = 0; 468 int sceneThrottleBps = 0;
449 bool usePools = false; 469 bool usePools = false;
450 470
471
472
451 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 473 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
452 if (config != null) 474 if (config != null)
453 { 475 {
@@ -494,15 +516,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
494 } 516 }
495 #endregion BinaryStats 517 #endregion BinaryStats
496 518
497 // FIXME: Can't add info here because don't know scene yet. 519 Throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f);
498// m_throttle
499// = new TokenBucket(
500// string.Format("server throttle bucket for {0}", Scene.Name), null, sceneThrottleBps);
501
502 Throttle = new TokenBucket("server throttle bucket", null, 0, sceneThrottleBps);
503
504 ThrottleRates = new ThrottleRates(configSource); 520 ThrottleRates = new ThrottleRates(configSource);
505 521
522 Random rnd = new Random(Util.EnvironmentTickCount());
523 m_animationSequenceNumber = rnd.Next(11474826);
524
506 if (usePools) 525 if (usePools)
507 EnablePools(); 526 EnablePools();
508 } 527 }
@@ -798,8 +817,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
798 if (UsePools) 817 if (UsePools)
799 EnablePoolStats(); 818 EnablePoolStats();
800 819
820
801 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this); 821 LLUDPServerCommands commands = new LLUDPServerCommands(MainConsole.Instance, this);
802 commands.Register(); 822 commands.Register();
823
803 } 824 }
804 825
805 public bool HandlesRegion(Location x) 826 public bool HandlesRegion(Location x)
@@ -907,8 +928,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
907 928
908 PacketPool.Instance.ReturnPacket(packet); 929 PacketPool.Instance.ReturnPacket(packet);
909 930
910 if (packetQueued) 931 /// WRONG use. May be usefull in future revision
911 m_dataPresentEvent.Set(); 932// if (packetQueued)
933// m_dataPresentEvent.Set();
912 } 934 }
913 935
914 /// <summary> 936 /// <summary>
@@ -969,8 +991,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
969 bufferSize = dataLength; 991 bufferSize = dataLength;
970 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 992 buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
971 993
972 // m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" + 994 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
973 // type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet"); 995 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length);
974 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 996 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
975 } 997 }
976 } 998 }
@@ -979,6 +1001,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 1001
980 #region Queue or Send 1002 #region Queue or Send
981 1003
1004 bool highPriority = false;
1005
1006 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
1007 {
1008 category = (ThrottleOutPacketType)((int)category & 127);
1009 highPriority = true;
1010 }
1011
982 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); 1012 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
983 1013
984 // If we were not provided a method for handling unacked, use the UDPServer default method 1014 // If we were not provided a method for handling unacked, use the UDPServer default method
@@ -988,26 +1018,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
988 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will 1018 // If a Linden Lab 1.23.5 client receives an update packet after a kill packet for an object, it will
989 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object 1019 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
990 // packet so that it isn't sent before a queued update packet. 1020 // packet so that it isn't sent before a queued update packet.
991 bool forceQueue = (type == PacketType.KillObject);
992 1021
993// if (type == PacketType.ImprovedTerseObjectUpdate) 1022 bool requestQueue = type == PacketType.KillObject;
994// { 1023 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
995// m_log.DebugFormat("Direct send ITOU to {0} in {1}", udpClient.AgentID, Scene.Name);
996// SendPacketFinal(outgoingPacket);
997// return false;
998// }
999// else
1000// {
1001 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, forceQueue))
1002 { 1024 {
1003 SendPacketFinal(outgoingPacket); 1025 SendPacketFinal(outgoingPacket);
1004 return true; 1026 return true;
1005 } 1027 }
1006 else 1028
1007 { 1029 return false;
1008 return false;
1009 }
1010// }
1011 1030
1012 #endregion Queue or Send 1031 #endregion Queue or Send
1013 } 1032 }
@@ -1048,6 +1067,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1048 pc.PingID.OldestUnacked = 0; 1067 pc.PingID.OldestUnacked = 0;
1049 1068
1050 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null); 1069 SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false, null);
1070 udpClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1051 } 1071 }
1052 1072
1053 public void CompletePing(LLUDPClient udpClient, byte pingID) 1073 public void CompletePing(LLUDPClient udpClient, byte pingID)
@@ -1145,7 +1165,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1145 int dataLength = buffer.DataLength; 1165 int dataLength = buffer.DataLength;
1146 1166
1147 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here 1167 // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here
1148 if (!isZerocoded) 1168 if (!isZerocoded && !isResend && outgoingPacket.UnackedMethod == null)
1149 { 1169 {
1150 // Keep appending ACKs until there is no room left in the buffer or there are 1170 // Keep appending ACKs until there is no room left in the buffer or there are
1151 // no more ACKs to append 1171 // no more ACKs to append
@@ -1180,7 +1200,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1180 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1); 1200 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
1181 outgoingPacket.SequenceNumber = sequenceNumber; 1201 outgoingPacket.SequenceNumber = sequenceNumber;
1182 1202
1183 if (udpClient.ProcessUnackedSends && isReliable) 1203 if (isReliable)
1184 { 1204 {
1185 // Add this packet to the list of ACK responses we are waiting on from the server 1205 // Add this packet to the list of ACK responses we are waiting on from the server
1186 udpClient.NeedAcks.Add(outgoingPacket); 1206 udpClient.NeedAcks.Add(outgoingPacket);
@@ -1311,35 +1331,62 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1311 1331
1312 #region Packet to Client Mapping 1332 #region Packet to Client Mapping
1313 1333
1314 // UseCircuitCode handling 1334 // If there is already a client for this endpoint, don't process UseCircuitCode
1315 if (packet.Type == PacketType.UseCircuitCode) 1335 IClientAPI client = null;
1336 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1316 { 1337 {
1317 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1338 // UseCircuitCode handling
1318 // buffer. 1339 if (packet.Type == PacketType.UseCircuitCode)
1319 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1340 {
1341 // And if there is a UseCircuitCode pending, also drop it
1342 lock (m_pendingCache)
1343 {
1344 if (m_pendingCache.Contains(endPoint))
1345 return;
1320 1346
1321 Util.FireAndForget(HandleUseCircuitCode, array, "LLUDPServer.HandleUseCircuitCode"); 1347 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1348 }
1322 1349
1323 return; 1350 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1351 // buffer.
1352 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1353
1354 Util.FireAndForget(HandleUseCircuitCode, array);
1355
1356 return;
1357 }
1324 } 1358 }
1325 else if (packet.Type == PacketType.CompleteAgentMovement) 1359
1360 // If this is a pending connection, enqueue, don't process yet
1361 lock (m_pendingCache)
1326 { 1362 {
1327 // Send ack straight away to let the viewer know that we got it. 1363 Queue<UDPPacketBuffer> queue;
1328 SendAckImmediate(endPoint, packet.Header.Sequence); 1364 if (m_pendingCache.TryGetValue(endPoint, out queue))
1365 {
1366 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1367 queue.Enqueue(buffer);
1368 return;
1369 }
1329 1370
1330 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1371/*
1331 // buffer. 1372 else if (packet.Type == PacketType.CompleteAgentMovement)
1332 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1373 {
1374 // Send ack straight away to let the viewer know that we got it.
1375 SendAckImmediate(endPoint, packet.Header.Sequence);
1333 1376
1334 Util.FireAndForget( 1377 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1335 HandleCompleteMovementIntoRegion, array, "LLUDPServer.HandleCompleteMovementIntoRegion"); 1378 // buffer.
1379 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1336 1380
1337 return; 1381 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1382
1383 return;
1384 }
1385 */
1338 } 1386 }
1339 1387
1340 // Determine which agent this packet came from 1388 // Determine which agent this packet came from
1341 IClientAPI client; 1389 if (client == null || !(client is LLClientView))
1342 if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1343 { 1390 {
1344 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1391 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1345 1392
@@ -1356,7 +1403,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1356 udpClient = ((LLClientView)client).UDPClient; 1403 udpClient = ((LLClientView)client).UDPClient;
1357 1404
1358 if (!udpClient.IsConnected) 1405 if (!udpClient.IsConnected)
1406 {
1407 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + Scene.RegionInfo.RegionName);
1359 return; 1408 return;
1409 }
1360 1410
1361 #endregion Packet to Client Mapping 1411 #endregion Packet to Client Mapping
1362 1412
@@ -1368,37 +1418,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1368 1418
1369 #region ACK Receiving 1419 #region ACK Receiving
1370 1420
1371 if (udpClient.ProcessUnackedSends) 1421 // Handle appended ACKs
1422 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
1372 { 1423 {
1373 // Handle appended ACKs 1424 // m_log.DebugFormat(
1374 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 1425 // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1375 { 1426 // packet.Header.AckList.Length, client.Name, m_scene.Name);
1376 // m_log.DebugFormat(
1377 // "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1378 // packet.Header.AckList.Length, client.Name, m_scene.Name);
1379 1427
1380 for (int i = 0; i < packet.Header.AckList.Length; i++) 1428 for (int i = 0; i < packet.Header.AckList.Length; i++)
1381 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1429 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
1382 } 1430 }
1383 1431
1384 // Handle PacketAck packets 1432 // Handle PacketAck packets
1385 if (packet.Type == PacketType.PacketAck) 1433 if (packet.Type == PacketType.PacketAck)
1386 { 1434 {
1387 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1435 PacketAckPacket ackPacket = (PacketAckPacket)packet;
1388 1436
1389 // m_log.DebugFormat( 1437 // m_log.DebugFormat(
1390 // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", 1438 // "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1391 // ackPacket.Packets.Length, client.Name, m_scene.Name); 1439 // ackPacket.Packets.Length, client.Name, m_scene.Name);
1392 1440
1393 for (int i = 0; i < ackPacket.Packets.Length; i++) 1441 for (int i = 0; i < ackPacket.Packets.Length; i++)
1394 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1442 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
1395 1443
1396 // We don't need to do anything else with PacketAck packets 1444 // We don't need to do anything else with PacketAck packets
1397 return;
1398 }
1399 }
1400 else if (packet.Type == PacketType.PacketAck)
1401 {
1402 return; 1445 return;
1403 } 1446 }
1404 1447
@@ -1459,24 +1502,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1459 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1502 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1460 #endregion BinaryStats 1503 #endregion BinaryStats
1461 1504
1462 if (packet.Type == PacketType.AgentUpdate)
1463 {
1464 if (DiscardInboundAgentUpdates)
1465 return;
1466 1505
1467 ((LLClientView)client).TotalAgentUpdates++; 1506//AgentUpdate removed from here
1468 1507
1469 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
1470
1471 LLClientView llClient = client as LLClientView;
1472 if (agentUpdate.AgentData.SessionID != client.SessionId
1473 || agentUpdate.AgentData.AgentID != client.AgentId
1474 || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) )
1475 {
1476 PacketPool.Instance.ReturnPacket(packet);
1477 return;
1478 }
1479 }
1480 1508
1481 #region Ping Check Handling 1509 #region Ping Check Handling
1482 1510
@@ -1487,7 +1515,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1487 // We don't need to do anything else with ping checks 1515 // We don't need to do anything else with ping checks
1488 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1516 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
1489 CompletePing(udpClient, startPing.PingID.PingID); 1517 CompletePing(udpClient, startPing.PingID.PingID);
1490 1518
1491 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000) 1519 if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000)
1492 { 1520 {
1493 udpClient.SendPacketStats(); 1521 udpClient.SendPacketStats();
@@ -1497,7 +1525,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1497 } 1525 }
1498 else if (packet.Type == PacketType.CompletePingCheck) 1526 else if (packet.Type == PacketType.CompletePingCheck)
1499 { 1527 {
1500 // We don't currently track client ping times 1528 int t = Util.EnvironmentTickCountSubtract(udpClient.m_lastStartpingTimeMS);
1529 int c = udpClient.m_pingMS;
1530 c = 800 * c + 200 * t;
1531 c /= 1000;
1532 udpClient.m_pingMS = c;
1501 return; 1533 return;
1502 } 1534 }
1503 1535
@@ -1517,7 +1549,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1517 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1549 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1518 } 1550 }
1519 1551
1520 packetInbox.Enqueue(incomingPacket); 1552// if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1553// incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1554 if (incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1555 packetInbox.EnqueueHigh(incomingPacket);
1556 else
1557 packetInbox.EnqueueLow(incomingPacket);
1558
1521 } 1559 }
1522 1560
1523 #region BinaryStats 1561 #region BinaryStats
@@ -1634,7 +1672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1634 1672
1635 try 1673 try
1636 { 1674 {
1637 // DateTime startTime = DateTime.Now; 1675// DateTime startTime = DateTime.Now;
1638 object[] array = (object[])o; 1676 object[] array = (object[])o;
1639 endPoint = (IPEndPoint)array[0]; 1677 endPoint = (IPEndPoint)array[0];
1640 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1678 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
@@ -1646,6 +1684,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1646 AuthenticateResponse sessionInfo; 1684 AuthenticateResponse sessionInfo;
1647 if (IsClientAuthorized(uccp, out sessionInfo)) 1685 if (IsClientAuthorized(uccp, out sessionInfo))
1648 { 1686 {
1687 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1688
1649 // Begin the process of adding the client to the simulator 1689 // Begin the process of adding the client to the simulator
1650 client 1690 client
1651 = AddClient( 1691 = AddClient(
@@ -1654,20 +1694,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1654 uccp.CircuitCode.SessionID, 1694 uccp.CircuitCode.SessionID,
1655 endPoint, 1695 endPoint,
1656 sessionInfo); 1696 sessionInfo);
1657 1697
1698 // This will be true if the client is new, e.g. not
1699 // an existing child agent, and there is no circuit data
1700 if (client != null && aCircuit == null)
1701 {
1702 Scene.CloseAgent(client.AgentId, true);
1703 return;
1704 }
1705
1706 // Now we know we can handle more data
1707 Thread.Sleep(200);
1708
1709 // Obtain the pending queue and remove it from the cache
1710 Queue<UDPPacketBuffer> queue = null;
1711
1712 lock (m_pendingCache)
1713 {
1714 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1715 {
1716 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1717 return;
1718
1719 }
1720 m_pendingCache.Remove(endPoint);
1721 }
1722
1723 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1724
1725 // Reinject queued packets
1726 while (queue.Count > 0)
1727 {
1728 UDPPacketBuffer buf = queue.Dequeue();
1729 PacketReceived(buf);
1730 }
1731
1732 queue = null;
1733
1658 // Send ack straight away to let the viewer know that the connection is active. 1734 // Send ack straight away to let the viewer know that the connection is active.
1659 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1735 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1660 // circuit code to the existing child agent. This is not particularly obvious. 1736 // circuit code to the existing child agent. This is not particularly obvious.
1661 SendAckImmediate(endPoint, uccp.Header.Sequence); 1737 SendAckImmediate(endPoint, uccp.Header.Sequence);
1662 1738
1663 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1739 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1664 if (client != null) 1740 if (client != null)
1665 { 1741 {
1666 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1667 bool tp = (aCircuit.teleportFlags > 0); 1742 bool tp = (aCircuit.teleportFlags > 0);
1668 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from 1743 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1669 if (!tp && !client.SceneAgent.SentInitialDataToClient) 1744 if (!tp)
1670 client.SceneAgent.SendInitialDataToClient(); 1745 client.SceneAgent.SendInitialDataToMe();
1671 } 1746 }
1672 } 1747 }
1673 else 1748 else
@@ -1675,9 +1750,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1675 // Don't create clients for unauthorized requesters. 1750 // Don't create clients for unauthorized requesters.
1676 m_log.WarnFormat( 1751 m_log.WarnFormat(
1677 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1752 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1753
1678 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1754 uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1679 } 1755
1680 1756 lock (m_pendingCache)
1757 m_pendingCache.Remove(endPoint);
1758 }
1759
1681 // m_log.DebugFormat( 1760 // m_log.DebugFormat(
1682 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms", 1761 // "[LLUDPSERVER]: Handling UseCircuitCode request from {0} took {1}ms",
1683 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds); 1762 // buffer.RemoteEndPoint, (DateTime.Now - startTime).Milliseconds);
@@ -1694,8 +1773,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1694 e.StackTrace); 1773 e.StackTrace);
1695 } 1774 }
1696 } 1775 }
1697 1776/*
1698 private void HandleCompleteMovementIntoRegion(object o) 1777 private void HandleCompleteMovementIntoRegion(object o)
1699 { 1778 {
1700 IPEndPoint endPoint = null; 1779 IPEndPoint endPoint = null;
1701 IClientAPI client = null; 1780 IClientAPI client = null;
@@ -1804,6 +1883,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1804 e.StackTrace); 1883 e.StackTrace);
1805 } 1884 }
1806 } 1885 }
1886*/
1807 1887
1808 /// <summary> 1888 /// <summary>
1809 /// Send an ack immediately to the given endpoint. 1889 /// Send an ack immediately to the given endpoint.
@@ -1861,6 +1941,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1861 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo) 1941 uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
1862 { 1942 {
1863 IClientAPI client = null; 1943 IClientAPI client = null;
1944 bool createNew = false;
1864 1945
1865 // We currently synchronize this code across the whole scene to avoid issues such as 1946 // We currently synchronize this code across the whole scene to avoid issues such as
1866 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done 1947 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
@@ -1869,7 +1950,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1869 { 1950 {
1870 if (!Scene.TryGetClient(agentID, out client)) 1951 if (!Scene.TryGetClient(agentID, out client))
1871 { 1952 {
1953 createNew = true;
1954 }
1955 else
1956 {
1957 if (client.SceneAgent == null)
1958 {
1959 Scene.CloseAgent(agentID, true);
1960 createNew = true;
1961 }
1962 }
1963
1964 if (createNew)
1965 {
1872 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1966 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, Throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1967
1873 1968
1874 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1969 client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1875 client.OnLogout += LogoutHandler; 1970 client.OnLogout += LogoutHandler;
@@ -1899,15 +1994,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1899 { 1994 {
1900 ClientLogoutsDueToNoReceives++; 1995 ClientLogoutsDueToNoReceives++;
1901 1996
1902 m_log.WarnFormat( 1997 if (client.SceneAgent != null)
1903 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", 1998 {
1904 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name); 1999 m_log.WarnFormat(
2000 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
2001 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name);
1905 2002
1906 if (!client.SceneAgent.IsChildAgent) 2003 if (!client.SceneAgent.IsChildAgent)
1907 client.Kick("Simulator logged you out due to connection timeout."); 2004 client.Kick("Simulator logged you out due to connection timeout.");
2005 }
1908 } 2006 }
1909 2007
1910 Scene.CloseAgent(client.AgentId, true); 2008 if (!Scene.CloseAgent(client.AgentId, true))
2009 client.Close(true,true);
1911 } 2010 }
1912 2011
1913 private void IncomingPacketHandler() 2012 private void IncomingPacketHandler()
@@ -1920,6 +2019,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1920 2019
1921 while (IsRunningInbound) 2020 while (IsRunningInbound)
1922 { 2021 {
2022 Scene.ThreadAlive(1);
1923 try 2023 try
1924 { 2024 {
1925 IncomingPacket incomingPacket = null; 2025 IncomingPacket incomingPacket = null;
@@ -1942,7 +2042,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1942 m_incomingPacketPool.ReturnObject(incomingPacket); 2042 m_incomingPacketPool.ReturnObject(incomingPacket);
1943 } 2043 }
1944 } 2044 }
1945 catch (Exception ex) 2045 catch(Exception ex)
1946 { 2046 {
1947 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 2047 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
1948 } 2048 }
@@ -1971,6 +2071,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1971 2071
1972 while (base.IsRunningOutbound) 2072 while (base.IsRunningOutbound)
1973 { 2073 {
2074 Scene.ThreadAlive(2);
1974 try 2075 try
1975 { 2076 {
1976 m_packetSent = false; 2077 m_packetSent = false;
@@ -2029,13 +2130,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2029 2130
2030 // If nothing was sent, sleep for the minimum amount of time before a 2131 // If nothing was sent, sleep for the minimum amount of time before a
2031 // token bucket could get more tokens 2132 // token bucket could get more tokens
2032 //if (!m_packetSent) 2133
2033 // Thread.Sleep((int)TickCountResolution);
2034 //
2035 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
2036 // modern mono it reduces CPU base load since there is no more continuous polling.
2037 if (!m_packetSent) 2134 if (!m_packetSent)
2038 m_dataPresentEvent.WaitOne(100); 2135 Thread.Sleep((int)TickCountResolution);
2136
2137 // .... wrong core code removed
2138
2039 2139
2040 Watchdog.UpdateThread(); 2140 Watchdog.UpdateThread();
2041 } 2141 }
@@ -2061,7 +2161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2061 2161
2062 if (udpClient.IsConnected) 2162 if (udpClient.IsConnected)
2063 { 2163 {
2064 if (udpClient.ProcessUnackedSends && m_resendUnacked) 2164 if (m_resendUnacked)
2065 HandleUnacked(llClient); 2165 HandleUnacked(llClient);
2066 2166
2067 if (m_sendAcks) 2167 if (m_sendAcks)
@@ -2206,8 +2306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2206 Packet packet = incomingPacket.Packet; 2306 Packet packet = incomingPacket.Packet;
2207 LLClientView client = incomingPacket.Client; 2307 LLClientView client = incomingPacket.Client;
2208 2308
2209 if (client.IsActive) 2309// if (client.IsActive)
2210 { 2310// {
2211 m_currentIncomingClient = client; 2311 m_currentIncomingClient = client;
2212 2312
2213 try 2313 try
@@ -2234,13 +2334,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2234 { 2334 {
2235 m_currentIncomingClient = null; 2335 m_currentIncomingClient = null;
2236 } 2336 }
2237 } 2337// }
2238 else 2338// else
2239 { 2339// {
2240 m_log.DebugFormat( 2340// m_log.DebugFormat(
2241 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 2341// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
2242 packet.Type, client.Name, Scene.RegionInfo.RegionName); 2342// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
2243 } 2343// }
2244 2344
2245 IncomingPacketsProcessed++; 2345 IncomingPacketsProcessed++;
2246 } 2346 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
index ac6c0b4..6e6a2d1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServerCommands.cs
@@ -48,6 +48,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
48 48
49 public void Register() 49 public void Register()
50 { 50 {
51/*
51 m_console.Commands.AddCommand( 52 m_console.Commands.AddCommand(
52 "Comms", false, "show server throttles", 53 "Comms", false, "show server throttles",
53 "show server throttles", 54 "show server throttles",
@@ -213,6 +214,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
213 "Set a debug parameter for a particular client. If no name is given then the value is set on all clients.", 214 "Set a debug parameter for a particular client. If no name is given then the value is set on all clients.",
214 "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.", 215 "process-unacked-sends - Do we take action if a sent reliable packet has not been acked.",
215 HandleClientSetCommand); 216 HandleClientSetCommand);
217*/
216 } 218 }
217 219
218 private void HandleShowServerThrottlesCommand(string module, string[] args) 220 private void HandleShowServerThrottlesCommand(string module, string[] args)
@@ -224,7 +226,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
224 ConsoleDisplayList cdl = new ConsoleDisplayList(); 226 ConsoleDisplayList cdl = new ConsoleDisplayList();
225 cdl.AddRow("Adaptive throttles", m_udpServer.ThrottleRates.AdaptiveThrottlesEnabled); 227 cdl.AddRow("Adaptive throttles", m_udpServer.ThrottleRates.AdaptiveThrottlesEnabled);
226 228
227 long maxSceneDripRate = m_udpServer.Throttle.MaxDripRate; 229 long maxSceneDripRate = (long)m_udpServer.Throttle.MaxDripRate;
228 cdl.AddRow( 230 cdl.AddRow(
229 "Max scene throttle", 231 "Max scene throttle",
230 maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset"); 232 maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset");
@@ -505,7 +507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
505 m_console.OutputFormat("Debug settings for {0}", m_udpServer.Scene.Name); 507 m_console.OutputFormat("Debug settings for {0}", m_udpServer.Scene.Name);
506 ConsoleDisplayList cdl = new ConsoleDisplayList(); 508 ConsoleDisplayList cdl = new ConsoleDisplayList();
507 509
508 long maxSceneDripRate = m_udpServer.Throttle.MaxDripRate; 510 long maxSceneDripRate = (long)m_udpServer.Throttle.MaxDripRate;
509 cdl.AddRow( 511 cdl.AddRow(
510 "max-scene-throttle", 512 "max-scene-throttle",
511 maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset"); 513 maxSceneDripRate != 0 ? string.Format("{0} kbps", maxSceneDripRate * 8 / 1000) : "unset");
@@ -556,6 +558,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
556 m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name); 558 m_console.OutputFormat("{0} set to {1} in {2}", param, rawValue, m_udpServer.Scene.Name);
557 } 559 }
558 560
561/* not in use, nothing to set/get from lludp
559 private void HandleClientGetCommand(string module, string[] args) 562 private void HandleClientGetCommand(string module, string[] args)
560 { 563 {
561 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) 564 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
@@ -582,11 +585,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
582 m_console.OutputFormat( 585 m_console.OutputFormat(
583 "Client debug parameters for {0} ({1}) in {2}", 586 "Client debug parameters for {0} ({1}) in {2}",
584 sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name); 587 sp.Name, sp.IsChildAgent ? "child" : "root", m_udpServer.Scene.Name);
585
586 ConsoleDisplayList cdl = new ConsoleDisplayList();
587 cdl.AddRow("process-unacked-sends", udpClient.ProcessUnackedSends);
588
589 m_console.Output(cdl.ToString());
590 } 588 }
591 }); 589 });
592 } 590 }
@@ -609,28 +607,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
609 607
610 if (args.Length == 8) 608 if (args.Length == 8)
611 name = string.Format("{0} {1}", args[6], args[7]); 609 name = string.Format("{0} {1}", args[6], args[7]);
612 610 // nothing here now
613 if (param == "process-unacked-sends")
614 {
615 bool newValue;
616
617 if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newValue))
618 return;
619
620 m_udpServer.Scene.ForEachScenePresence(
621 sp =>
622 {
623 if ((name == null || sp.Name == name) && sp.ControllingClient is LLClientView)
624 {
625 LLUDPClient udpClient = ((LLClientView)sp.ControllingClient).UDPClient;
626 udpClient.ProcessUnackedSends = newValue;
627
628 m_console.OutputFormat("{0} set to {1} for {2} in {3}", param, newValue, sp.Name, m_udpServer.Scene.Name);
629 }
630 });
631 }
632 } 611 }
633 612*/
634 private void HandlePacketCommand(string module, string[] args) 613 private void HandlePacketCommand(string module, string[] args)
635 { 614 {
636 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) 615 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index f62dc15..7171974 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -206,16 +206,16 @@ namespace OpenMetaverse
206 const int SIO_UDP_CONNRESET = -1744830452; 206 const int SIO_UDP_CONNRESET = -1744830452;
207 207
208 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 208 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
209
210 m_log.DebugFormat(
211 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
212 ipep.Address, ipep.Port);
213 209
214 m_udpSocket = new Socket( 210 m_udpSocket = new Socket(
215 AddressFamily.InterNetwork, 211 AddressFamily.InterNetwork,
216 SocketType.Dgram, 212 SocketType.Dgram,
217 ProtocolType.Udp); 213 ProtocolType.Udp);
218 214
215 // OpenSim may need this but in AVN, this messes up automated
216 // sim restarts badly
217 //m_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, false);
218
219 try 219 try
220 { 220 {
221 if (m_udpSocket.Ttl < 128) 221 if (m_udpSocket.Ttl < 128)
@@ -501,4 +501,4 @@ namespace OpenMetaverse
501 catch (ObjectDisposedException) { } 501 catch (ObjectDisposedException) { }
502 } 502 }
503 } 503 }
504} \ No newline at end of file 504}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
index 3c82a78..5e41dbd 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/ThrottleTests.cs
@@ -35,6 +35,7 @@ using OpenSim.Tests.Common;
35 35
36namespace OpenSim.Region.ClientStack.LindenUDP.Tests 36namespace OpenSim.Region.ClientStack.LindenUDP.Tests
37{ 37{
38 /*
38 [TestFixture] 39 [TestFixture]
39 public class ThrottleTests : OpenSimTestCase 40 public class ThrottleTests : OpenSimTestCase
40 { 41 {
@@ -57,16 +58,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
57 [Test] 58 [Test]
58 public void TestSetRequestDripRate() 59 public void TestSetRequestDripRate()
59 { 60 {
61
60 TestHelpers.InMethod(); 62 TestHelpers.InMethod();
61 63
62 TokenBucket tb = new TokenBucket("tb", null, 5000, 0); 64 TokenBucket tb = new TokenBucket(null, 5000f,10000f);
63 AssertRates(tb, 5000, 0, 5000, 0); 65 AssertRates(tb, 5000, 0, 5000, 0);
64 66
65 tb.RequestedDripRate = 4000; 67 tb.RequestedDripRate = 4000f;
66 AssertRates(tb, 4000, 0, 4000, 0); 68 AssertRates(tb, 4000, 0, 4000, 0);
67 69
68 tb.RequestedDripRate = 6000; 70 tb.RequestedDripRate = 6000;
69 AssertRates(tb, 6000, 0, 6000, 0); 71 AssertRates(tb, 6000, 0, 6000, 0);
72
70 } 73 }
71 74
72 [Test] 75 [Test]
@@ -74,7 +77,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
74 { 77 {
75 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
76 79
77 TokenBucket tb = new TokenBucket("tb", null, 5000, 10000); 80 TokenBucket tb = new TokenBucket(null, 5000,15000);
78 AssertRates(tb, 5000, 0, 5000, 10000); 81 AssertRates(tb, 5000, 0, 5000, 10000);
79 82
80 tb.RequestedDripRate = 4000; 83 tb.RequestedDripRate = 4000;
@@ -92,9 +95,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
92 { 95 {
93 TestHelpers.InMethod(); 96 TestHelpers.InMethod();
94 97
95 TokenBucket tbParent = new TokenBucket("tbParent", null, 0, 0); 98 TokenBucket tbParent = new TokenBucket("tbParent", null, 0);
96 TokenBucket tbChild1 = new TokenBucket("tbChild1", tbParent, 3000, 0); 99 TokenBucket tbChild1 = new TokenBucket("tbChild1", tbParent, 3000);
97 TokenBucket tbChild2 = new TokenBucket("tbChild2", tbParent, 5000, 0); 100 TokenBucket tbChild2 = new TokenBucket("tbChild2", tbParent, 5000);
98 101
99 AssertRates(tbParent, 8000, 8000, 8000, 0); 102 AssertRates(tbParent, 8000, 8000, 8000, 0);
100 AssertRates(tbChild1, 3000, 0, 3000, 0); 103 AssertRates(tbChild1, 3000, 0, 3000, 0);
@@ -113,6 +116,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
113 AssertRates(tbParent, 6000, 8000, 6000, 0); 116 AssertRates(tbParent, 6000, 8000, 6000, 0);
114 AssertRates(tbChild1, 3000, 0, 6000 / 8 * 3, 0); 117 AssertRates(tbChild1, 3000, 0, 6000 / 8 * 3, 0);
115 AssertRates(tbChild2, 5000, 0, 6000 / 8 * 5, 0); 118 AssertRates(tbChild2, 5000, 0, 6000 / 8 * 5, 0);
119
116 } 120 }
117 121
118 private void AssertRates( 122 private void AssertRates(
@@ -424,4 +428,5 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
424 udpClient.SetThrottles(throttles); 428 udpClient.SetThrottles(throttles);
425 } 429 }
426 } 430 }
431 */
427} \ No newline at end of file 432} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index 7a2756b..076551f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -69,6 +69,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
69 /// <summary>Amount of the texture throttle to steal for the task throttle</summary> 69 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
70 public double CannibalizeTextureRate; 70 public double CannibalizeTextureRate;
71 71
72 public int ClientMaxRate;
73 public float BrustTime;
74
72 /// <summary> 75 /// <summary>
73 /// Default constructor 76 /// Default constructor
74 /// </summary> 77 /// </summary>
@@ -88,7 +91,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
88 Texture = throttleConfig.GetInt("texture_default", 18500); 91 Texture = throttleConfig.GetInt("texture_default", 18500);
89 Asset = throttleConfig.GetInt("asset_default", 10500); 92 Asset = throttleConfig.GetInt("asset_default", 10500);
90 93
91 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); 94 Total = Resend + Land + Wind + Cloud + Task + Texture + Asset;
95 // 3000000 bps default max
96 ClientMaxRate = throttleConfig.GetInt("client_throttle_max_bps", 375000);
97 if (ClientMaxRate > 1000000)
98 ClientMaxRate = 1000000; // no more than 8Mbps
99
100 BrustTime = (float)throttleConfig.GetInt("client_throttle_burtsTimeMS", 10);
101 BrustTime *= 1e-3f;
92 102
93 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 103 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
94 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000); 104 MinimumAdaptiveThrottleRate = throttleConfig.GetInt("adaptive_throttle_min_bps", 32000);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
index 4616203..0f71222 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/TokenBucket.cs
@@ -43,25 +43,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
43 { 43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 public string Identifier { get; private set; } 46 private static Int32 m_counter = 0;
47
48 public int DebugLevel { get; set; }
49 47
50 /// <summary> 48// private Int32 m_identifier;
51 /// Number of ticks (ms) per quantum, drip rate and max burst 49
52 /// are defined over this interval. 50 protected const float m_timeScale = 1e-3f;
53 /// </summary>
54 protected const Int32 m_ticksPerQuantum = 1000;
55 51
56 /// <summary> 52 /// <summary>
57 /// This is the number of quantums worth of packets that can 53 /// This is the number of m_minimumDripRate bytes
58 /// be accommodated during a burst 54 /// allowed in a burst
55 /// roughtly, with this settings, the maximum time system will take
56 /// to recheck a bucket in ms
57 ///
59 /// </summary> 58 /// </summary>
60 protected const Double m_quantumsPerBurst = 1.5; 59 protected const float m_quantumsPerBurst = 5;
61 60
62 /// <summary> 61 /// <summary>
63 /// </summary> 62 /// </summary>
64 protected const Int32 m_minimumDripRate = LLUDPServer.MTU; 63 protected const float m_minimumDripRate = 1500;
65 64
66 /// <summary>Time of the last drip, in system ticks</summary> 65 /// <summary>Time of the last drip, in system ticks</summary>
67 protected Int32 m_lastDrip; 66 protected Int32 m_lastDrip;
@@ -70,40 +69,57 @@ namespace OpenSim.Region.ClientStack.LindenUDP
70 /// The number of bytes that can be sent at this moment. This is the 69 /// The number of bytes that can be sent at this moment. This is the
71 /// current number of tokens in the bucket 70 /// current number of tokens in the bucket
72 /// </summary> 71 /// </summary>
73 protected Int64 m_tokenCount; 72 protected float m_tokenCount;
74 73
75 /// <summary> 74 /// <summary>
76 /// Map of children buckets and their requested maximum burst rate 75 /// Map of children buckets and their requested maximum burst rate
77 /// </summary> 76 /// </summary>
78 protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>(); 77
78 protected Dictionary<TokenBucket, float> m_children = new Dictionary<TokenBucket, float>();
79
80#region Properties
79 81
80 /// <summary> 82 /// <summary>
81 /// The parent bucket of this bucket, or null if this bucket has no 83 /// The parent bucket of this bucket, or null if this bucket has no
82 /// parent. The parent bucket will limit the aggregate bandwidth of all 84 /// parent. The parent bucket will limit the aggregate bandwidth of all
83 /// of its children buckets 85 /// of its children buckets
84 /// </summary> 86 /// </summary>
85 public TokenBucket Parent { get; protected set; } 87 protected TokenBucket m_parent;
86 88 public TokenBucket Parent
89 {
90 get { return m_parent; }
91 set { m_parent = value; }
92 }
87 /// <summary> 93 /// <summary>
88 /// Maximum burst rate in bytes per second. This is the maximum number 94 /// This is the maximum number
89 /// of tokens that can accumulate in the bucket at any one time. This 95 /// of tokens that can accumulate in the bucket at any one time. This
90 /// also sets the total request for leaf nodes 96 /// also sets the total request for leaf nodes
91 /// </summary> 97 /// </summary>
92 protected Int64 m_burstRate; 98 protected float m_burst;
93 public Int64 RequestedBurstRate 99//not in use
100 public float MaxDripRate { get; set; }
101
102 public float RequestedBurst
94 { 103 {
95 get { return m_burstRate; } 104 get { return m_burst; }
96 set { m_burstRate = (value < 0 ? 0 : value); } 105 set {
106 float rate = (value < 0 ? 0 : value);
107 if (rate < 1.5f * m_minimumDripRate)
108 rate = 1.5f * m_minimumDripRate;
109 else if (rate > m_minimumDripRate * m_quantumsPerBurst)
110 rate = m_minimumDripRate * m_quantumsPerBurst;
111
112 m_burst = rate;
113 }
97 } 114 }
98 115
99 public Int64 BurstRate 116 public float Burst
100 { 117 {
101 get { 118 get {
102 double rate = RequestedBurstRate * BurstRateModifier(); 119 float rate = RequestedBurst * BurstModifier();
103 if (rate < m_minimumDripRate * m_quantumsPerBurst) 120 if (rate < m_minimumDripRate)
104 rate = m_minimumDripRate * m_quantumsPerBurst; 121 rate = m_minimumDripRate;
105 122 return (float)rate;
106 return (Int64) rate;
107 } 123 }
108 } 124 }
109 125
@@ -115,78 +131,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP
115 /// Can never be above MaxDripRate. 131 /// Can never be above MaxDripRate.
116 /// Tokens are added to the bucket at any time 132 /// Tokens are added to the bucket at any time
117 /// <seealso cref="RemoveTokens"/> is called, at the granularity of 133 /// <seealso cref="RemoveTokens"/> is called, at the granularity of
118 /// the system tick interval (typically around 15-22ms) 134 /// the system tick interval (typically around 15-22ms)</remarks>
119 /// FIXME: It is extremely confusing to be able to set a RequestedDripRate of 0 and then receive a positive 135 protected float m_dripRate;
120 /// number on get if TotalDripRequest is set. This also stops us being able to retrieve the fact that
121 /// RequestedDripRate is set to 0. Really, this should always return m_dripRate and then we can get
122 /// (m_dripRate == 0 ? TotalDripRequest : m_dripRate) on some other properties.
123 /// </remarks>
124 public virtual Int64 RequestedDripRate
125 {
126 get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); }
127 set
128 {
129 if (value <= 0)
130 m_dripRate = 0;
131 else if (MaxDripRate > 0 && value > MaxDripRate)
132 m_dripRate = MaxDripRate;
133 else
134 m_dripRate = value;
135 136
136 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst); 137 public virtual float RequestedDripRate
138 {
139 get { return (m_dripRate == 0 ? m_totalDripRequest : m_dripRate); }
140 set {
141 m_dripRate = (value < 0 ? 0 : value);
142 m_totalDripRequest = m_dripRate;
137 143
138 if (Parent != null) 144 if (m_parent != null)
139 Parent.RegisterRequest(this, m_dripRate); 145 m_parent.RegisterRequest(this,m_dripRate);
140 } 146 }
141 } 147 }
142 148
143 /// <summary> 149 public virtual float DripRate
144 /// Gets the drip rate.
145 /// </summary>
146 /// <value>
147 /// DripRate can never be above max drip rate or below min drip rate.
148 /// If we are a child bucket then the drip rate return is modifed by the total load on the capacity of the
149 /// parent bucket.
150 /// </value>
151 public virtual Int64 DripRate
152 { 150 {
153 get 151 get {
154 { 152 float rate = Math.Min(RequestedDripRate,TotalDripRequest);
155 double rate; 153 if (m_parent == null)
156 154 return rate;
157 // FIXME: This doesn't properly work if we have a parent and children and a requested drip rate set
158 // on ourselves which is not equal to the child drip rates.
159 if (Parent == null)
160 {
161 if (TotalDripRequest > 0)
162 rate = Math.Min(RequestedDripRate, TotalDripRequest);
163 else
164 rate = RequestedDripRate;
165 }
166 else
167 {
168 rate = (double)RequestedDripRate * Parent.DripRateModifier();
169 }
170 155
156 rate *= m_parent.DripRateModifier();
171 if (rate < m_minimumDripRate) 157 if (rate < m_minimumDripRate)
172 rate = m_minimumDripRate; 158 rate = m_minimumDripRate;
173 else if (MaxDripRate > 0 && rate > MaxDripRate)
174 rate = MaxDripRate;
175 159
176 return (Int64)rate; 160 return (float)rate;
177 } 161 }
178 } 162 }
179 protected Int64 m_dripRate;
180
181 // <summary>
182 // The maximum rate for flow control. Drip rate can never be greater than this.
183 // </summary>
184 public Int64 MaxDripRate { get; set; }
185 163
186 /// <summary> 164 /// <summary>
187 /// The current total of the requested maximum burst rates of children buckets. 165 /// The current total of the requested maximum burst rates of children buckets.
188 /// </summary> 166 /// </summary>
189 public Int64 TotalDripRequest { get; protected set; } 167 protected float m_totalDripRequest;
168 public float TotalDripRequest
169 {
170 get { return m_totalDripRequest; }
171 set { m_totalDripRequest = value; }
172 }
173
174#endregion Properties
175
176#region Constructor
177
190 178
191 /// <summary> 179 /// <summary>
192 /// Default constructor 180 /// Default constructor
@@ -194,20 +182,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
194 /// <param name="identifier">Identifier for this token bucket</param> 182 /// <param name="identifier">Identifier for this token bucket</param>
195 /// <param name="parent">Parent bucket if this is a child bucket, or 183 /// <param name="parent">Parent bucket if this is a child bucket, or
196 /// null if this is a root bucket</param> 184 /// null if this is a root bucket</param>
197 /// <param name="requestedDripRate"> 185 /// <param name="maxBurst">Maximum size of the bucket in bytes, or
198 /// Requested rate that the bucket fills, in bytes per 186 /// zero if this bucket has no maximum capacity</param>
199 /// second. If zero, the bucket always remains full. 187 /// <param name="dripRate">Rate that the bucket fills, in bytes per
200 /// </param> 188 /// second. If zero, the bucket always remains full</param>
201 public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate) 189 public TokenBucket(TokenBucket parent, float dripRate, float MaxBurst)
202 { 190 {
203 Identifier = identifier; 191 m_counter++;
204 192
205 Parent = parent; 193 Parent = parent;
206 RequestedDripRate = requestedDripRate; 194 RequestedDripRate = dripRate;
207 MaxDripRate = maxDripRate; 195 RequestedBurst = MaxBurst;
208 m_lastDrip = Util.EnvironmentTickCount(); 196 // TotalDripRequest = dripRate; // this will be overwritten when a child node registers
197 // MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
198 m_lastDrip = Util.EnvironmentTickCount() + 100000;
209 } 199 }
210 200
201#endregion Constructor
202
211 /// <summary> 203 /// <summary>
212 /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning 204 /// Compute a modifier for the MaxBurst rate. This is 1.0, meaning
213 /// no modification if the requested bandwidth is less than the 205 /// no modification if the requested bandwidth is less than the
@@ -215,22 +207,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
215 /// hierarchy. However, if any of the parents is over-booked, then 207 /// hierarchy. However, if any of the parents is over-booked, then
216 /// the modifier will be less than 1. 208 /// the modifier will be less than 1.
217 /// </summary> 209 /// </summary>
218 protected double DripRateModifier() 210 protected float DripRateModifier()
219 { 211 {
220 Int64 driprate = DripRate; 212 float driprate = DripRate;
221 double modifier = driprate >= TotalDripRequest ? 1.0 : (double)driprate / (double)TotalDripRequest; 213 return driprate >= TotalDripRequest ? 1.0f : driprate / TotalDripRequest;
222
223// if (DebugLevel > 0)
224// m_log.DebugFormat(
225// "[TOKEN BUCKET]: Returning drip modifier {0}/{1} = {2} from {3}",
226// driprate, TotalDripRequest, modifier, Identifier);
227
228 return modifier;
229 } 214 }
230 215
231 /// <summary> 216 /// <summary>
232 /// </summary> 217 /// </summary>
233 protected double BurstRateModifier() 218 protected float BurstModifier()
234 { 219 {
235 // for now... burst rate is always m_quantumsPerBurst (constant) 220 // for now... burst rate is always m_quantumsPerBurst (constant)
236 // larger than drip rate so the ratio of burst requests is the 221 // larger than drip rate so the ratio of burst requests is the
@@ -242,29 +227,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
242 /// Register drip rate requested by a child of this throttle. Pass the 227 /// Register drip rate requested by a child of this throttle. Pass the
243 /// changes up the hierarchy. 228 /// changes up the hierarchy.
244 /// </summary> 229 /// </summary>
245 public void RegisterRequest(TokenBucket child, Int64 request) 230 public void RegisterRequest(TokenBucket child, float request)
246 { 231 {
247 lock (m_children) 232 lock (m_children)
248 { 233 {
249 m_children[child] = request; 234 m_children[child] = request;
250 235
251 TotalDripRequest = 0; 236 m_totalDripRequest = 0;
252 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 237 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
253 TotalDripRequest += cref.Value; 238 m_totalDripRequest += cref.Value;
254 } 239 }
255 240
256 // Pass the new values up to the parent 241 // Pass the new values up to the parent
257 if (Parent != null) 242 if (m_parent != null)
258 { 243 m_parent.RegisterRequest(this, Math.Min(RequestedDripRate, TotalDripRequest));
259 Int64 effectiveDripRate;
260
261 if (RequestedDripRate > 0)
262 effectiveDripRate = Math.Min(RequestedDripRate, TotalDripRequest);
263 else
264 effectiveDripRate = TotalDripRequest;
265
266 Parent.RegisterRequest(this, effectiveDripRate);
267 }
268 } 244 }
269 245
270 /// <summary> 246 /// <summary>
@@ -277,9 +253,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
277 { 253 {
278 m_children.Remove(child); 254 m_children.Remove(child);
279 255
280 TotalDripRequest = 0; 256 m_totalDripRequest = 0;
281 foreach (KeyValuePair<TokenBucket, Int64> cref in m_children) 257 foreach (KeyValuePair<TokenBucket, float> cref in m_children)
282 TotalDripRequest += cref.Value; 258 m_totalDripRequest += cref.Value;
283 } 259 }
284 260
285 // Pass the new values up to the parent 261 // Pass the new values up to the parent
@@ -293,7 +269,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 /// <param name="amount">Number of tokens to remove from the bucket</param> 269 /// <param name="amount">Number of tokens to remove from the bucket</param>
294 /// <returns>True if the requested number of tokens were removed from 270 /// <returns>True if the requested number of tokens were removed from
295 /// the bucket, otherwise false</returns> 271 /// the bucket, otherwise false</returns>
296 public bool RemoveTokens(Int64 amount) 272 public bool RemoveTokens(int amount)
297 { 273 {
298 // Deposit tokens for this interval 274 // Deposit tokens for this interval
299 Drip(); 275 Drip();
@@ -310,19 +286,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
310 return false; 286 return false;
311 } 287 }
312 288
313 /// <summary> 289 public bool CheckTokens(int amount)
314 /// Deposit tokens into the bucket from a child bucket that did
315 /// not use all of its available tokens
316 /// </summary>
317 protected void Deposit(Int64 count)
318 { 290 {
319 m_tokenCount += count; 291 return (m_tokenCount - amount >= 0);
292 }
320 293
321 // Deposit the overflow in the parent bucket, this is how we share 294 public int GetCatBytesCanSend(int timeMS)
322 // unused bandwidth 295 {
323 Int64 burstrate = BurstRate; 296// return (int)(m_tokenCount + timeMS * m_dripRate * 1e-3);
324 if (m_tokenCount > burstrate) 297 return (int)(timeMS * DripRate * 1e-3);
325 m_tokenCount = burstrate;
326 } 298 }
327 299
328 /// <summary> 300 /// <summary>
@@ -337,21 +309,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
337 // with no drip rate... 309 // with no drip rate...
338 if (DripRate == 0) 310 if (DripRate == 0)
339 { 311 {
340 m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", Identifier); 312 m_log.WarnFormat("[TOKENBUCKET] something odd is happening and drip rate is 0 for {0}", m_counter);
341 return; 313 return;
342 } 314 }
343 315
344 // Determine the interval over which we are adding tokens, never add 316 Int32 now = Util.EnvironmentTickCount();
345 // more than a single quantum of tokens 317 Int32 deltaMS = now - m_lastDrip;
346 Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum); 318 m_lastDrip = now;
347 m_lastDrip = Util.EnvironmentTickCount();
348 319
349 // This can be 0 in the very unusual case that the timer wrapped
350 // It can be 0 if we try add tokens at a sub-tick rate
351 if (deltaMS <= 0) 320 if (deltaMS <= 0)
352 return; 321 return;
353 322
354 Deposit(deltaMS * DripRate / m_ticksPerQuantum); 323 m_tokenCount += deltaMS * DripRate * m_timeScale;
324
325 float burst = Burst;
326 if (m_tokenCount > burst)
327 m_tokenCount = burst;
355 } 328 }
356 } 329 }
357 330
@@ -362,103 +335,79 @@ namespace OpenSim.Region.ClientStack.LindenUDP
362 public bool AdaptiveEnabled { get; set; } 335 public bool AdaptiveEnabled { get; set; }
363 336
364 /// <summary> 337 /// <summary>
365 /// Target drip rate for this bucket. 338 /// The minimum rate for flow control. Minimum drip rate is one
339 /// packet per second.
366 /// </summary> 340 /// </summary>
367 /// <remarks>Usually set by the client. If adaptive is enabled then throttles will increase until we reach this.</remarks> 341
368 public Int64 TargetDripRate 342 protected const float m_minimumFlow = 50000;
369 { 343
370 get { return m_targetDripRate; } 344 // <summary>
371 set 345 // The maximum rate for flow control. Drip rate can never be
346 // greater than this.
347 // </summary>
348
349 protected float m_maxDripRate = 0;
350 public float MaxDripRate
351 {
352 get { return (m_maxDripRate == 0 ? m_totalDripRequest : m_maxDripRate); }
353 set
372 { 354 {
373 m_targetDripRate = Math.Max(value, m_minimumFlow); 355 m_maxDripRate = (value == 0 ? m_totalDripRequest : Math.Max(value, m_minimumFlow));
374 } 356 }
375 } 357 }
376 protected Int64 m_targetDripRate; 358
359 private bool m_enabled = false;
377 360
378 // <summary> 361 // <summary>
379 // Adjust drip rate in response to network conditions. 362 // Adjust drip rate in response to network conditions.
380 // </summary> 363 // </summary>
381 public virtual Int64 AdjustedDripRate 364 public virtual float AdjustedDripRate
382 { 365 {
383 get { return m_dripRate; } 366 get { return m_dripRate; }
384 set 367 set
385 { 368 {
386 m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate); 369 m_dripRate = OpenSim.Framework.Util.Clamp<float>(value, m_minimumFlow, MaxDripRate);
387 m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
388 370
389 if (Parent != null) 371 if (m_parent != null)
390 Parent.RegisterRequest(this, m_dripRate); 372 m_parent.RegisterRequest(this, m_dripRate);
391 } 373 }
392 } 374 }
393 375
394 /// <summary> 376
395 /// The minimum rate for adaptive flow control. 377 // <summary>
396 /// </summary> 378 //
397 protected Int64 m_minimumFlow = 32000; 379 // </summary>
398 380 public AdaptiveTokenBucket(TokenBucket parent, float maxDripRate, float maxBurst, bool enabled)
399 /// <summary> 381 : base(parent, maxDripRate, maxBurst)
400 /// Constructor for the AdaptiveTokenBucket class
401 /// <param name="identifier">Unique identifier for the client</param>
402 /// <param name="parent">Parent bucket in the hierarchy</param>
403 /// <param name="requestedDripRate"></param>
404 /// <param name="maxDripRate">The ceiling rate for adaptation</param>
405 /// <param name="minDripRate">The floor rate for adaptation</param>
406 /// </summary>
407 public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate, Int64 minDripRate, bool enabled)
408 : base(identifier, parent, requestedDripRate, maxDripRate)
409 { 382 {
410 AdaptiveEnabled = enabled; 383 m_enabled = enabled;
411 384
412 if (AdaptiveEnabled) 385 MaxDripRate = maxDripRate;
413 { 386
414// m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled"); 387 if (enabled)
415 m_minimumFlow = minDripRate; 388 AdjustedDripRate = m_maxDripRate * .5f;
416 TargetDripRate = m_minimumFlow; 389 else
417 AdjustedDripRate = m_minimumFlow; 390 AdjustedDripRate = m_maxDripRate;
418 }
419 } 391 }
420 392
421 /// <summary> 393 /// <summary>
422 /// Reliable packets sent to the client for which we never received an ack adjust the drip rate down. 394 /// Reliable packets sent to the client for which we never received an ack adjust the drip rate down.
423 /// <param name="packets">Number of packets that expired without successful delivery</param> 395 /// <param name="packets">Number of packets that expired without successful delivery</param>
424 /// </summary> 396 /// </summary>
425 public void ExpirePackets(Int32 packets) 397 public void ExpirePackets(Int32 count)
426 { 398 {
427 if (AdaptiveEnabled) 399 // m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
428 { 400 if (m_enabled)
429 if (DebugLevel > 0) 401 AdjustedDripRate = (Int64)(AdjustedDripRate / Math.Pow(2, count));
430 m_log.WarnFormat(
431 "[ADAPTIVEBUCKET] drop {0} by {1} expired packets for {2}",
432 AdjustedDripRate, packets, Identifier);
433
434 // AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,packets));
435
436 // Compute the fallback solely on the rate allocated beyond the minimum, this
437 // should smooth out the fallback to the minimum rate
438 AdjustedDripRate = m_minimumFlow + (Int64) ((AdjustedDripRate - m_minimumFlow) / Math.Pow(2, packets));
439 }
440 } 402 }
441 403
442 /// <summary> 404 // <summary>
443 /// Reliable packets acked by the client adjust the drip rate up. 405 //
444 /// <param name="packets">Number of packets successfully acknowledged</param> 406 // </summary>
445 /// </summary> 407 public void AcknowledgePackets(Int32 count)
446 public void AcknowledgePackets(Int32 packets)
447 {
448 if (AdaptiveEnabled)
449 AdjustedDripRate = AdjustedDripRate + packets * LLUDPServer.MTU;
450 }
451
452 /// <summary>
453 /// Adjust the minimum flow level for the adaptive throttle, this will drop adjusted
454 /// throttles back to the minimum levels
455 /// <param>minDripRate--the new minimum flow</param>
456 /// </summary>
457 public void ResetMinimumAdaptiveFlow(Int64 minDripRate)
458 { 408 {
459 m_minimumFlow = minDripRate; 409 if (m_enabled)
460 TargetDripRate = m_minimumFlow; 410 AdjustedDripRate = AdjustedDripRate + count;
461 AdjustedDripRate = m_minimumFlow;
462 } 411 }
463 } 412 }
464} \ No newline at end of file 413}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index f56d17d..1a19585 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -152,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
152 } 152 }
153 } 153 }
154 154
155 public void RequestCreateInventoryItem(IClientAPI remoteClient, 155 public bool RequestCreateInventoryItem(IClientAPI remoteClient,
156 UUID transactionID, UUID folderID, uint callbackID, 156 UUID transactionID, UUID folderID, uint callbackID,
157 string description, string name, sbyte invType, 157 string description, string name, sbyte invType,
158 sbyte type, byte wearableType, uint nextOwnerMask) 158 sbyte type, byte wearableType, uint nextOwnerMask)
@@ -162,6 +162,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
162 uploader.RequestCreateInventoryItem( 162 uploader.RequestCreateInventoryItem(
163 remoteClient, folderID, callbackID, 163 remoteClient, folderID, callbackID,
164 description, name, invType, type, wearableType, nextOwnerMask); 164 description, name, invType, type, wearableType, nextOwnerMask);
165
166 return true;
165 } 167 }
166 168
167 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, 169 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
@@ -170,6 +172,17 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
170 { 172 {
171 AssetXferUploader uploader = RequestXferUploader(transactionID); 173 AssetXferUploader uploader = RequestXferUploader(transactionID);
172 174
175 // Here we need to get the old asset to extract the
176 // texture UUIDs if it's a wearable.
177 if (item.Type == (int)AssetType.Bodypart ||
178 item.Type == (int)AssetType.Clothing ||
179 item.Type == (int)CustomAssetType.AnimationSet)
180 {
181 AssetBase oldAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
182 if (oldAsset != null)
183 uploader.SetOldData(oldAsset.Data);
184 }
185
173 uploader.RequestUpdateTaskInventoryItem(remoteClient, item); 186 uploader.RequestUpdateTaskInventoryItem(remoteClient, item);
174 } 187 }
175 188
@@ -178,7 +191,18 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
178 { 191 {
179 AssetXferUploader uploader = RequestXferUploader(transactionID); 192 AssetXferUploader uploader = RequestXferUploader(transactionID);
180 193
194 // Here we need to get the old asset to extract the
195 // texture UUIDs if it's a wearable.
196 if (item.AssetType == (int)AssetType.Bodypart ||
197 item.AssetType == (int)AssetType.Clothing ||
198 item.AssetType == (int)CustomAssetType.AnimationSet)
199 {
200 AssetBase oldAsset = m_Scene.AssetService.Get(item.AssetID.ToString());
201 if (oldAsset != null)
202 uploader.SetOldData(oldAsset.Data);
203 }
204
181 uploader.RequestUpdateInventoryItem(remoteClient, item); 205 uploader.RequestUpdateInventoryItem(remoteClient, item);
182 } 206 }
183 } 207 }
184} \ No newline at end of file 208}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index b67c0df..f489262 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
158 /// <param name="type"></param> 158 /// <param name="type"></param>
159 /// <param name="wearableType"></param> 159 /// <param name="wearableType"></param>
160 /// <param name="nextOwnerMask"></param> 160 /// <param name="nextOwnerMask"></param>
161 public void HandleItemCreationFromTransaction(IClientAPI remoteClient, 161 public bool HandleItemCreationFromTransaction(IClientAPI remoteClient,
162 UUID transactionID, UUID folderID, uint callbackID, 162 UUID transactionID, UUID folderID, uint callbackID,
163 string description, string name, sbyte invType, 163 string description, string name, sbyte invType,
164 sbyte type, byte wearableType, uint nextOwnerMask) 164 sbyte type, byte wearableType, uint nextOwnerMask)
@@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
169 AgentAssetTransactions transactions = 169 AgentAssetTransactions transactions =
170 GetUserTransactions(remoteClient.AgentId); 170 GetUserTransactions(remoteClient.AgentId);
171 171
172 transactions.RequestCreateInventoryItem(remoteClient, transactionID, 172 return transactions.RequestCreateInventoryItem(remoteClient, transactionID,
173 folderID, callbackID, description, name, invType, type, 173 folderID, callbackID, description, name, invType, type,
174 wearableType, nextOwnerMask); 174 wearableType, nextOwnerMask);
175 } 175 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index 5143204..c14e89f 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Collections.Generic;
31using log4net; 32using log4net;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
@@ -40,6 +41,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
40{ 41{
41 public class AssetXferUploader 42 public class AssetXferUploader
42 { 43 {
44 // Viewer's notion of the default texture
45 private List<UUID> defaultIDs = new List<UUID> {
46 new UUID("5748decc-f629-461c-9a36-a35a221fe21f"),
47 new UUID("7ca39b4c-bd19-4699-aff7-f93fd03d3e7b"),
48 new UUID("6522e74d-1660-4e7f-b601-6f48c1659a77"),
49 new UUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97")
50 };
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 52
45 /// <summary> 53 /// <summary>
@@ -87,6 +95,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
87 95
88 private sbyte type = 0; 96 private sbyte type = 0;
89 private byte wearableType = 0; 97 private byte wearableType = 0;
98 private byte[] m_oldData = null;
90 public ulong XferID; 99 public ulong XferID;
91 private Scene m_Scene; 100 private Scene m_Scene;
92 101
@@ -129,18 +138,27 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
129 138
130 if (XferID == xferID) 139 if (XferID == xferID)
131 { 140 {
132 if (m_asset.Data.Length > 1) 141 lock (this)
133 { 142 {
134 byte[] destinationArray = new byte[m_asset.Data.Length + data.Length]; 143 int assetLength = m_asset.Data.Length;
135 Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length); 144 int dataLength = data.Length;
136 Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length); 145
137 m_asset.Data = destinationArray; 146 if (m_asset.Data.Length > 1)
138 } 147 {
139 else 148 byte[] destinationArray = new byte[assetLength + dataLength];
140 { 149 Array.Copy(m_asset.Data, 0, destinationArray, 0, assetLength);
141 byte[] buffer2 = new byte[data.Length - 4]; 150 Array.Copy(data, 0, destinationArray, assetLength, dataLength);
142 Array.Copy(data, 4, buffer2, 0, data.Length - 4); 151 m_asset.Data = destinationArray;
143 m_asset.Data = buffer2; 152 }
153 else
154 {
155 if (dataLength > 4)
156 {
157 byte[] buffer2 = new byte[dataLength - 4];
158 Array.Copy(data, 4, buffer2, 0, dataLength - 4);
159 m_asset.Data = buffer2;
160 }
161 }
144 } 162 }
145 163
146 ourClient.SendConfirmXfer(xferID, packetID); 164 ourClient.SendConfirmXfer(xferID, packetID);
@@ -244,10 +262,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
244 { 262 {
245 CompleteTaskItemUpdate(m_updateTaskItemData); 263 CompleteTaskItemUpdate(m_updateTaskItemData);
246 } 264 }
247// else if (m_storeLocal) 265 else if (m_asset.Local)
248// { 266 {
249// m_Scene.AssetService.Store(m_asset); 267 m_Scene.AssetService.Store(m_asset);
250// } 268 }
251 } 269 }
252 270
253 m_log.DebugFormat( 271 m_log.DebugFormat(
@@ -319,14 +337,16 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
319 m_asset.Description = item.Description; 337 m_asset.Description = item.Description;
320 m_asset.Type = (sbyte)item.AssetType; 338 m_asset.Type = (sbyte)item.AssetType;
321 339
322 if (m_asset.FullID != UUID.Zero) 340 // remove redundante m_Scene.InventoryService.UpdateItem
323 { 341 // if uploadState == UploadState.Complete)
342// if (m_asset.FullID != UUID.Zero)
343// {
324 // We must always store the item at this point even if the asset hasn't finished uploading, in order 344 // We must always store the item at this point even if the asset hasn't finished uploading, in order
325 // to avoid a race condition when the appearance module retrieves the item to set the asset id in 345 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
326 // the AvatarAppearance structure. 346 // the AvatarAppearance structure.
327 item.AssetID = m_asset.FullID; 347// item.AssetID = m_asset.FullID;
328 m_Scene.InventoryService.UpdateItem(item); 348// m_Scene.InventoryService.UpdateItem(item);
329 } 349// }
330 350
331 if (m_uploadState == UploadState.Complete) 351 if (m_uploadState == UploadState.Complete)
332 { 352 {
@@ -334,10 +354,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
334 } 354 }
335 else 355 else
336 { 356 {
337// m_log.DebugFormat( 357 // do it here to avoid the eventual race condition
338// "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}", 358 if (m_asset.FullID != UUID.Zero)
339// item.Name, remoteClient.Name, transactionID); 359 {
340 360 // We must always store the item at this point even if the asset hasn't finished uploading, in order
361 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
362 // the AvatarAppearance structure.
363 item.AssetID = m_asset.FullID;
364 m_Scene.InventoryService.UpdateItem(item);
365 }
366
367
368 // m_log.DebugFormat(
369 // "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}",
370 // item.Name, remoteClient.Name, transactionID);
371
341 m_updateItem = true; 372 m_updateItem = true;
342 m_updateItemData = item; 373 m_updateItemData = item;
343 } 374 }
@@ -376,7 +407,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
376// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", 407// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
377// m_asset.FullID, item.Name, ourClient.Name); 408// m_asset.FullID, item.Name, ourClient.Name);
378 409
410 ValidateAssets();
379 m_Scene.AssetService.Store(m_asset); 411 m_Scene.AssetService.Store(m_asset);
412 if (m_asset.FullID != UUID.Zero)
413 {
414 item.AssetID = m_asset.FullID;
415 m_Scene.InventoryService.UpdateItem(item);
416 }
417
418 ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0);
380 419
381 m_transactions.RemoveXferUploader(m_transactionID); 420 m_transactions.RemoveXferUploader(m_transactionID);
382 421
@@ -393,6 +432,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
393// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", 432// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
394// m_asset.FullID, taskItem.Name, ourClient.Name); 433// m_asset.FullID, taskItem.Name, ourClient.Name);
395 434
435 ValidateAssets();
396 m_Scene.AssetService.Store(m_asset); 436 m_Scene.AssetService.Store(m_asset);
397 437
398 m_transactions.RemoveXferUploader(m_transactionID); 438 m_transactions.RemoveXferUploader(m_transactionID);
@@ -400,6 +440,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
400 440
401 private void CompleteCreateItem(uint callbackID) 441 private void CompleteCreateItem(uint callbackID)
402 { 442 {
443 ValidateAssets();
403 m_Scene.AssetService.Store(m_asset); 444 m_Scene.AssetService.Store(m_asset);
404 445
405 InventoryItemBase item = new InventoryItemBase(); 446 InventoryItemBase item = new InventoryItemBase();
@@ -420,13 +461,159 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
420 item.Flags = (uint) wearableType; 461 item.Flags = (uint) wearableType;
421 item.CreationDate = Util.UnixTimeSinceEpoch(); 462 item.CreationDate = Util.UnixTimeSinceEpoch();
422 463
464 m_log.DebugFormat("[XFER]: Created item {0} with asset {1}",
465 item.ID, item.AssetID);
466
423 if (m_Scene.AddInventoryItem(item)) 467 if (m_Scene.AddInventoryItem(item))
424 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 468 ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, callbackID);
425 else 469 else
426 ourClient.SendAlertMessage("Unable to create inventory item"); 470 ourClient.SendAlertMessage("Unable to create inventory item");
427 471
428 m_transactions.RemoveXferUploader(m_transactionID); 472 m_transactions.RemoveXferUploader(m_transactionID);
429 } 473 }
430 474
475
476 private void ValidateAssets()
477 {
478 if (m_asset.Type == (sbyte)CustomAssetType.AnimationSet)
479 {
480 AnimationSet animSet = new AnimationSet(m_asset.Data);
481
482 bool allOk = animSet.Validate(x => {
483 int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x);
484 int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
485 if ((perms & required) != required)
486 return false;
487 return true;
488 });
489
490 if (!allOk)
491 m_asset.Data = animSet.ToBytes();
492 }
493
494 if (m_asset.Type == (sbyte)AssetType.Clothing ||
495 m_asset.Type == (sbyte)AssetType.Bodypart)
496 {
497 string content = System.Text.Encoding.ASCII.GetString(m_asset.Data);
498 string[] lines = content.Split(new char[] {'\n'});
499
500 List<string> validated = new List<string>();
501
502 Dictionary<int, UUID> allowed = ExtractTexturesFromOldData();
503
504 int textures = 0;
505
506 foreach (string line in lines)
507 {
508 try
509 {
510 if (line.StartsWith("textures "))
511 {
512 textures = Convert.ToInt32(line.Substring(9));
513 validated.Add(line);
514 }
515 else if (textures > 0)
516 {
517 string[] parts = line.Split(new char[] {' '});
518
519 UUID tx = new UUID(parts[1]);
520 int id = Convert.ToInt32(parts[0]);
521
522 if (defaultIDs.Contains(tx) || tx == UUID.Zero ||
523 (allowed.ContainsKey(id) && allowed[id] == tx))
524 {
525 validated.Add(parts[0] + " " + tx.ToString());
526 }
527 else
528 {
529 int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
530 int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
531
532 if ((perms & full) != full)
533 {
534 m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId);
535 validated.Add(parts[0] + " " + UUID.Zero.ToString());
536 }
537 else
538 {
539 validated.Add(line);
540 }
541 }
542 textures--;
543 }
544 else
545 {
546 validated.Add(line);
547 }
548 }
549 catch
550 {
551 // If it's malformed, skip it
552 }
553 }
554
555 string final = String.Join("\n", validated.ToArray());
556
557 m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final);
558 }
559 }
560
561 /// <summary>
562 /// Get the asset data uploaded in this transfer.
563 /// </summary>
564 /// <returns>null if the asset has not finished uploading</returns>
565 public AssetBase GetAssetData()
566 {
567 if (m_uploadState == UploadState.Complete)
568 {
569 ValidateAssets();
570 return m_asset;
571 }
572
573 return null;
574 }
575
576 public void SetOldData(byte[] d)
577 {
578 m_oldData = d;
579 }
580
581 private Dictionary<int,UUID> ExtractTexturesFromOldData()
582 {
583 Dictionary<int,UUID> result = new Dictionary<int,UUID>();
584 if (m_oldData == null)
585 return result;
586
587 string content = System.Text.Encoding.ASCII.GetString(m_oldData);
588 string[] lines = content.Split(new char[] {'\n'});
589
590 int textures = 0;
591
592 foreach (string line in lines)
593 {
594 try
595 {
596 if (line.StartsWith("textures "))
597 {
598 textures = Convert.ToInt32(line.Substring(9));
599 }
600 else if (textures > 0)
601 {
602 string[] parts = line.Split(new char[] {' '});
603
604 UUID tx = new UUID(parts[1]);
605 int id = Convert.ToInt32(parts[0]);
606 result[id] = tx;
607 textures--;
608 }
609 }
610 catch
611 {
612 // If it's malformed, skip it
613 }
614 }
615
616 return result;
617 }
431 } 618 }
432} \ No newline at end of file 619}
diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
index 4299726..7113f4f 100644
--- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
@@ -160,6 +160,8 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
160 { 160 {
161 byte[] fileData = NewFiles[fileName].Data; 161 byte[] fileData = NewFiles[fileName].Data;
162 XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient); 162 XferDownLoad transaction = new XferDownLoad(fileName, fileData, xferID, remoteClient);
163 if (fileName.StartsWith("inventory_"))
164 transaction.isTaskInventory = true;
163 165
164 Transfers.Add(xferID, transaction); 166 Transfers.Add(xferID, transaction);
165 167
@@ -243,6 +245,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
243 public uint Packet = 0; 245 public uint Packet = 0;
244 public uint Serial = 1; 246 public uint Serial = 1;
245 public ulong XferID = 0; 247 public ulong XferID = 0;
248 public bool isTaskInventory = false;
246 249
247 public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client) 250 public XferDownLoad(string fileName, byte[] data, ulong xferID, IClientAPI client)
248 { 251 {
@@ -268,7 +271,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
268 byte[] transferData = new byte[Data.Length + 4]; 271 byte[] transferData = new byte[Data.Length + 4];
269 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); 272 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4);
270 Array.Copy(Data, 0, transferData, 4, Data.Length); 273 Array.Copy(Data, 0, transferData, 4, Data.Length);
271 Client.SendXferPacket(XferID, 0 + 0x80000000, transferData); 274 Client.SendXferPacket(XferID, 0 + 0x80000000, transferData, isTaskInventory);
272 complete = true; 275 complete = true;
273 } 276 }
274 else 277 else
@@ -276,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
276 byte[] transferData = new byte[1000 + 4]; 279 byte[] transferData = new byte[1000 + 4];
277 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4); 280 Array.Copy(Utils.IntToBytes(Data.Length), 0, transferData, 0, 4);
278 Array.Copy(Data, 0, transferData, 4, 1000); 281 Array.Copy(Data, 0, transferData, 4, 1000);
279 Client.SendXferPacket(XferID, 0, transferData); 282 Client.SendXferPacket(XferID, 0, transferData, isTaskInventory);
280 Packet++; 283 Packet++;
281 DataPointer = 1000; 284 DataPointer = 1000;
282 } 285 }
@@ -297,7 +300,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
297 { 300 {
298 byte[] transferData = new byte[1000]; 301 byte[] transferData = new byte[1000];
299 Array.Copy(Data, DataPointer, transferData, 0, 1000); 302 Array.Copy(Data, DataPointer, transferData, 0, 1000);
300 Client.SendXferPacket(XferID, Packet, transferData); 303 Client.SendXferPacket(XferID, Packet, transferData, isTaskInventory);
301 Packet++; 304 Packet++;
302 DataPointer += 1000; 305 DataPointer += 1000;
303 } 306 }
@@ -306,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
306 byte[] transferData = new byte[Data.Length - DataPointer]; 309 byte[] transferData = new byte[Data.Length - DataPointer];
307 Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer); 310 Array.Copy(Data, DataPointer, transferData, 0, Data.Length - DataPointer);
308 uint endPacket = Packet |= (uint) 0x80000000; 311 uint endPacket = Packet |= (uint) 0x80000000;
309 Client.SendXferPacket(XferID, endPacket, transferData); 312 Client.SendXferPacket(XferID, endPacket, transferData, isTaskInventory);
310 Packet++; 313 Packet++;
311 DataPointer += (Data.Length - DataPointer); 314 DataPointer += (Data.Length - DataPointer);
312 315
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 7d9c9a9..c4abc99 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -594,6 +594,11 @@ namespace OpenSim.Region.CoreModules.Asset
594 dir, dirSize); 594 dir, dirSize);
595 } 595 }
596 } 596 }
597 catch (DirectoryNotFoundException)
598 {
599 // If we get here, another node on the same box has
600 // already removed the directory. Continue with next.
601 }
597 catch (Exception e) 602 catch (Exception e)
598 { 603 {
599 m_log.Warn( 604 m_log.Warn(
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 2f67c4e..92beed2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -41,6 +41,7 @@ using OpenSim.Region.Framework;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Serialization; 43using OpenSim.Region.Framework.Scenes.Serialization;
44using OpenSim.Services.Interfaces;
44 45
45namespace OpenSim.Region.CoreModules.Avatar.Attachments 46namespace OpenSim.Region.CoreModules.Avatar.Attachments
46{ 47{
@@ -303,6 +304,40 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
303 if (DebugLevel > 0) 304 if (DebugLevel > 0)
304 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name); 305 m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing any attachments for {0} from simulator-side", sp.Name);
305 306
307 XmlDocument doc = new XmlDocument();
308 string stateData = String.Empty;
309
310 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
311 if (attServ != null)
312 {
313 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
314 stateData = attServ.Get(sp.UUID.ToString());
315 if (stateData != String.Empty)
316 {
317 try
318 {
319 doc.LoadXml(stateData);
320 }
321 catch { }
322 }
323 }
324
325 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
326
327 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
328 if (nodes.Count > 0)
329 {
330 foreach (XmlNode n in nodes)
331 {
332 XmlElement elem = (XmlElement)n;
333 string itemID = elem.GetAttribute("ItemID");
334 string xml = elem.InnerXml;
335
336 itemData[new UUID(itemID)] = xml;
337 }
338 }
339
340
306 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 341 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
307 342
308 // Let's get all items at once, so they get cached 343 // Let's get all items at once, so they get cached
@@ -330,10 +365,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
330 365
331 try 366 try
332 { 367 {
368 string xmlData;
369 XmlDocument d = null;
370 UUID asset;
371 if (itemData.TryGetValue(attach.ItemID, out xmlData))
372 {
373 d = new XmlDocument();
374 d.LoadXml(xmlData);
375 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", attach.ItemID);
376 }
377
333 // If we're an NPC then skip all the item checks and manipulations since we don't have an 378 // If we're an NPC then skip all the item checks and manipulations since we don't have an
334 // inventory right now. 379 // inventory right now.
335 RezSingleAttachmentFromInventoryInternal( 380 RezSingleAttachmentFromInventoryInternal(
336 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); 381 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
337 } 382 }
338 catch (Exception e) 383 catch (Exception e)
339 { 384 {
@@ -361,27 +406,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
361 406
362 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>(); 407 Dictionary<SceneObjectGroup, string> scriptStates = new Dictionary<SceneObjectGroup, string>();
363 408
364 foreach (SceneObjectGroup so in attachments)
365 {
366 // Scripts MUST be snapshotted before the object is
367 // removed from the scene because doing otherwise will
368 // clobber the run flag
369 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
370 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
371 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
372 409
373// m_log.DebugFormat( 410 if (sp.PresenceType != PresenceType.Npc)
374// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}",
375// so.Name, sp.Name, m_scene.Name, scriptStates[so]);
376 }
377
378 lock (sp.AttachmentsSyncLock)
379 { 411 {
380 foreach (SceneObjectGroup so in attachments) 412 foreach (SceneObjectGroup so in attachments)
381 UpdateDetachedObject(sp, so, scriptStates[so]); 413 {
382 414 // Scripts MUST be snapshotted before the object is
383 sp.ClearAttachments(); 415 // removed from the scene because doing otherwise will
416 // clobber the run flag
417 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
418 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
419 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
420 }
421
422 lock (sp.AttachmentsSyncLock)
423 {
424 foreach (SceneObjectGroup so in attachments)
425 UpdateDetachedObject(sp, so, scriptStates[so]);
426 sp.ClearAttachments();
427 }
384 } 428 }
429 else
430 {
431 lock (sp.AttachmentsSyncLock)
432 {
433 foreach (SceneObjectGroup so in attachments)
434 UpdateDetachedObject(sp, so, String.Empty);
435 sp.ClearAttachments();
436 }
437 }
385 } 438 }
386 439
387 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 440 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
@@ -402,20 +455,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
402 sp.ClearAttachments(); 455 sp.ClearAttachments();
403 } 456 }
404 457
405 public bool AttachObject( 458 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool append)
406 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool append)
407 { 459 {
408 if (!Enabled) 460 if (!Enabled)
409 return false; 461 return false;
410 462
411 group.DetachFromBackup(); 463 return AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, addToInventory, false, append);
412
413 bool success = AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append);
414
415 if (!success)
416 group.AttachToBackup();
417
418 return success;
419 } 464 }
420 465
421 /// <summary> 466 /// <summary>
@@ -428,10 +473,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
428 /// <param name='silent'></param> 473 /// <param name='silent'></param>
429 /// <param name='addToInventory'>If true then add object to user inventory.</param> 474 /// <param name='addToInventory'>If true then add object to user inventory.</param>
430 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param> 475 /// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
431 /// <param name='append'>Append to attachment point rather than replace.</param> 476 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool addToInventory, bool resumeScripts, bool append)
432 private bool AttachObjectInternal(
433 IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool addToInventory, bool resumeScripts, bool append)
434 { 477 {
478// m_log.DebugFormat(
479// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
480// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
481
482 if (sp.GetAttachments().Contains(group))
483 {
484// m_log.WarnFormat(
485// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
486// group.Name, group.LocalId, sp.Name, AttachmentPt);
487
488 return false;
489 }
490
435 if (group.GetSittingAvatarsCount() != 0) 491 if (group.GetSittingAvatarsCount() != 0)
436 { 492 {
437 if (DebugLevel > 0) 493 if (DebugLevel > 0)
@@ -443,6 +499,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
443 } 499 }
444 500
445 Vector3 attachPos = group.AbsolutePosition; 501 Vector3 attachPos = group.AbsolutePosition;
502
503 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
504 // be removed when that functionality is implemented in opensim
505 attachmentPt &= 0x7f;
506
446 // If the attachment point isn't the same as the one previously used 507 // If the attachment point isn't the same as the one previously used
447 // set it's offset position = 0 so that it appears on the attachment point 508 // set it's offset position = 0 so that it appears on the attachment point
448 // and not in a weird location somewhere unknown. 509 // and not in a weird location somewhere unknown.
@@ -481,9 +542,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
481 attachPos = Vector3.Zero; 542 attachPos = Vector3.Zero;
482 } 543 }
483 544
484 group.AttachmentPoint = attachmentPt;
485 group.AbsolutePosition = attachPos;
486
487 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 545 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
488 546
489 if (attachments.Contains(group)) 547 if (attachments.Contains(group))
@@ -516,6 +574,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
516 574
517 lock (sp.AttachmentsSyncLock) 575 lock (sp.AttachmentsSyncLock)
518 { 576 {
577 group.AttachmentPoint = attachmentPt;
578 group.AbsolutePosition = attachPos;
579
519 if (addToInventory && sp.PresenceType != PresenceType.Npc) 580 if (addToInventory && sp.PresenceType != PresenceType.Npc)
520 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); 581 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
521 582
@@ -546,7 +607,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
546 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append); 607 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
547 } 608 }
548 609
549 public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 610 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
611 {
612 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt, null);
613 }
614
615 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt, XmlDocument doc)
550 { 616 {
551 if (!Enabled) 617 if (!Enabled)
552 return null; 618 return null;
@@ -584,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
584 bool append = (AttachmentPt & 0x80) != 0; 650 bool append = (AttachmentPt & 0x80) != 0;
585 AttachmentPt &= 0x7f; 651 AttachmentPt &= 0x7f;
586 652
587 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append); 653 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, append, doc);
588 } 654 }
589 655
590 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 656 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -649,26 +715,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
649 if (changed && m_scene.AvatarFactory != null) 715 if (changed && m_scene.AvatarFactory != null)
650 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 716 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
651 717
718 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
719
652 sp.RemoveAttachment(so); 720 sp.RemoveAttachment(so);
653 so.FromItemID = UUID.Zero; 721 so.FromItemID = UUID.Zero;
654 722
723 so.AttachedAvatar = UUID.Zero;
724 so.ClearPartAttachmentData();
725
655 SceneObjectPart rootPart = so.RootPart; 726 SceneObjectPart rootPart = so.RootPart;
727
728 rootPart.SetParentLocalId(0);
656 so.AbsolutePosition = absolutePos; 729 so.AbsolutePosition = absolutePos;
657 if (absoluteRot != Quaternion.Identity) 730 if (absoluteRot != Quaternion.Identity)
658 { 731 {
659 so.UpdateGroupRotationR(absoluteRot); 732 so.UpdateGroupRotationR(absoluteRot);
660 } 733 }
661 so.AttachedAvatar = UUID.Zero; 734
662 rootPart.SetParentLocalId(0); 735 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
663 so.ClearPartAttachmentData(); 736
664 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive); 737 // not physical, not temporary, phaton, not volume detector
738// so.UpdatePrimFlags(rootPart.LocalId,false,false,true,rootPart.VolumeDetectActive);
739
740 // restore full physical state instead
741 so.ApplyPhysics();
742
665 so.HasGroupChanged = true; 743 so.HasGroupChanged = true;
666 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
667 rootPart.Rezzed = DateTime.Now; 744 rootPart.Rezzed = DateTime.Now;
668 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
669 so.AttachToBackup(); 745 so.AttachToBackup();
670 m_scene.EventManager.TriggerParcelPrimCountTainted(); 746 m_scene.EventManager.TriggerParcelPrimCountTainted();
671 rootPart.ScheduleFullUpdate(); 747
672 rootPart.ClearUndoState(); 748 rootPart.ClearUndoState();
673 749
674 List<UUID> uuids = new List<UUID>(); 750 List<UUID> uuids = new List<UUID>();
@@ -678,6 +754,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
678 } 754 }
679 755
680 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 756 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
757
758 // Attach (NULL) stops scripts. We don't want that. Resume them.
759 so.ResumeScripts();
760 so.ScheduleGroupForTerseUpdate();
761 so.RootPart.ScheduleFullUpdate();
681 } 762 }
682 763
683 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 764 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
@@ -848,8 +929,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
848 929
849 so.AttachedAvatar = sp.UUID; 930 so.AttachedAvatar = sp.UUID;
850 931
851 if (so.RootPart.PhysActor != null) 932 foreach (SceneObjectPart part in so.Parts)
852 so.RootPart.RemoveFromPhysics(); 933 {
934// if (part.KeyframeMotion != null)
935// part.KeyframeMotion.Suspend();
936
937 if (part.PhysActor != null)
938 {
939 part.RemoveFromPhysics();
940 }
941 }
853 942
854 so.AbsolutePosition = attachOffset; 943 so.AbsolutePosition = attachOffset;
855 so.RootPart.AttachedPos = attachOffset; 944 so.RootPart.AttachedPos = attachOffset;
@@ -971,6 +1060,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
971 // Remove the object from the scene so no more updates 1060 // Remove the object from the scene so no more updates
972 // are sent. Doing this before the below changes will ensure 1061 // are sent. Doing this before the below changes will ensure
973 // updates can't cause "HUD artefacts" 1062 // updates can't cause "HUD artefacts"
1063
974 m_scene.DeleteSceneObject(so, false, false); 1064 m_scene.DeleteSceneObject(so, false, false);
975 1065
976 // Prepare sog for storage 1066 // Prepare sog for storage
@@ -992,7 +1082,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
992 } 1082 }
993 1083
994 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 1084 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
995 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append) 1085 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, bool append, XmlDocument doc)
996 { 1086 {
997 if (m_invAccessModule == null) 1087 if (m_invAccessModule == null)
998 return null; 1088 return null;
@@ -1043,7 +1133,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1043 // This will throw if the attachment fails 1133 // This will throw if the attachment fails
1044 try 1134 try
1045 { 1135 {
1046 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append); 1136 if (doc != null)
1137 {
1138 objatt.LoadScriptState(doc);
1139 objatt.ResetOwnerChangeFlag();
1140 }
1141
1142 AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, true, append);
1047 } 1143 }
1048 catch (Exception e) 1144 catch (Exception e)
1049 { 1145 {
@@ -1197,7 +1293,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1197 AttachmentPt &= 0x7f; 1293 AttachmentPt &= 0x7f;
1198 1294
1199 // Calls attach with a Zero position 1295 // Calls attach with a Zero position
1200 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, append)) 1296 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false, true, append))
1201 { 1297 {
1202 if (DebugLevel > 0) 1298 if (DebugLevel > 0)
1203 m_log.Debug( 1299 m_log.Debug(
@@ -1205,7 +1301,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1205 + ", AttachmentPoint: " + AttachmentPt); 1301 + ", AttachmentPoint: " + AttachmentPt);
1206 1302
1207 // Save avatar attachment information 1303 // Save avatar attachment information
1208 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); 1304 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
1209 } 1305 }
1210 } 1306 }
1211 catch (Exception e) 1307 catch (Exception e)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 0ac3add..34b38b9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
200 Assert.That(so.Backup, Is.True); 200 Assert.That(so.Backup, Is.True);
201 201
202 m_numberOfAttachEventsFired = 0; 202 m_numberOfAttachEventsFired = 0;
203 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 203 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
204 204
205 // Check status on scene presence 205 // Check status on scene presence
206 Assert.That(sp.HasAttachments(), Is.True); 206 Assert.That(sp.HasAttachments(), Is.True);
@@ -248,7 +248,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
248 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID); 248 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "att1", sp.UUID);
249 249
250 m_numberOfAttachEventsFired = 0; 250 m_numberOfAttachEventsFired = 0;
251 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false); 251 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Default, false, true, false, false);
252 252
253 // Check status on scene presence 253 // Check status on scene presence
254 Assert.That(sp.HasAttachments(), Is.True); 254 Assert.That(sp.HasAttachments(), Is.True);
@@ -281,7 +281,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
281 281
282 // Test wearing a different attachment from the ground. 282 // Test wearing a different attachment from the ground.
283 { 283 {
284 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 284 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
285 285
286 // Check status on scene presence 286 // Check status on scene presence
287 Assert.That(sp.HasAttachments(), Is.True); 287 Assert.That(sp.HasAttachments(), Is.True);
@@ -314,7 +314,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
314 314
315 // Test rewearing an already worn attachment from ground. Nothing should happen. 315 // Test rewearing an already worn attachment from ground. Nothing should happen.
316 { 316 {
317 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false); 317 scene.AttachmentsModule.AttachObject(sp, so2, (uint)AttachmentPoint.Default, false, true, false, false);
318 318
319 // Check status on scene presence 319 // Check status on scene presence
320 Assert.That(sp.HasAttachments(), Is.True); 320 Assert.That(sp.HasAttachments(), Is.True);
@@ -372,7 +372,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
372 sp2.AbsolutePosition = new Vector3(0, 0, 0); 372 sp2.AbsolutePosition = new Vector3(0, 0, 0);
373 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 373 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
374 374
375 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false); 375 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, true, false, false);
376 376
377 Assert.That(sp.HasAttachments(), Is.False); 377 Assert.That(sp.HasAttachments(), Is.False);
378 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 378 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
@@ -670,7 +670,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
670 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 670 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
671 671
672 SceneObjectGroup rezzedSo 672 SceneObjectGroup rezzedSo
673 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 673 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
674 674
675 // Wait for chat to signal rezzed script has been started. 675 // Wait for chat to signal rezzed script has been started.
676 m_chatEvent.WaitOne(60000); 676 m_chatEvent.WaitOne(60000);
@@ -689,7 +689,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
689 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 689 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
690 690
691 // Re-rez the attachment to check script running state 691 // Re-rez the attachment to check script running state
692 SceneObjectGroup reRezzedSo = scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 692 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
693 693
694 // Wait for chat to signal rezzed script has been started. 694 // Wait for chat to signal rezzed script has been started.
695 m_chatEvent.WaitOne(60000); 695 m_chatEvent.WaitOne(60000);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index cfb082b..cdcd6b9 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -188,27 +188,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
188 // Process the visual params, this may change height as well 188 // Process the visual params, this may change height as well
189 if (visualParams != null) 189 if (visualParams != null)
190 { 190 {
191 // string[] visualParamsStrings = new string[visualParams.Length];
192 // for (int i = 0; i < visualParams.Length; i++)
193 // visualParamsStrings[i] = visualParams[i].ToString();
194 // m_log.DebugFormat(
195 // "[AVFACTORY]: Setting visual params for {0} to {1}",
196 // client.Name, string.Join(", ", visualParamsStrings));
197/*
198 float oldHeight = sp.Appearance.AvatarHeight;
199 changed = sp.Appearance.SetVisualParams(visualParams);
200
201 if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0)
202 ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight);
203 */
204// float oldoff = sp.Appearance.AvatarFeetOffset;
205// Vector3 oldbox = sp.Appearance.AvatarBoxSize;
206 changed = sp.Appearance.SetVisualParams(visualParams); 191 changed = sp.Appearance.SetVisualParams(visualParams);
207// float off = sp.Appearance.AvatarFeetOffset;
208// Vector3 box = sp.Appearance.AvatarBoxSize;
209// if(oldoff != off || oldbox != box)
210// ((ScenePresence)sp).SetSize(box,off);
211
212 } 192 }
213 193
214 // Process the baked texture array 194 // Process the baked texture array
@@ -222,9 +202,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
222 202
223// WriteBakedTexturesReport(sp, m_log.DebugFormat); 203// WriteBakedTexturesReport(sp, m_log.DebugFormat);
224 204
225 // If bake textures are missing and this is not an NPC, request a rebake from client 205 UpdateBakedTextureCache(sp, cacheItems);
226 if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc))
227 RequestRebake(sp, true);
228 206
229 // This appears to be set only in the final stage of the appearance 207 // This appears to be set only in the final stage of the appearance
230 // update transaction. In theory, we should be able to do an immediate 208 // update transaction. In theory, we should be able to do an immediate
@@ -251,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
251 private void SendAppearance(ScenePresence sp) 229 private void SendAppearance(ScenePresence sp)
252 { 230 {
253 // Send the appearance to everyone in the scene 231 // Send the appearance to everyone in the scene
254 sp.SendAppearanceToAllOtherClients(); 232 sp.SendAppearanceToAllOtherAgents();
255 233
256 // Send animations back to the avatar as well 234 // Send animations back to the avatar as well
257 sp.Animator.SendAnimPack(); 235 sp.Animator.SendAnimPack();
@@ -377,114 +355,322 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
377 } 355 }
378 } 356 }
379 357
380 public bool ValidateBakedTextureCache(IScenePresence sp) 358 // called on textures update
359 public bool UpdateBakedTextureCache(IScenePresence sp, WearableCacheItem[] cacheItems)
381 { 360 {
382 bool defonly = true; // are we only using default textures 361 // npcs dont have baked cache
383 IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 362 if (((ScenePresence)sp).isNPC)
384 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 363 return true;
385 WearableCacheItem[] wearableCache = null; 364
386 365 // uploaded baked textures will be in assets local cache
387 // Cache wearable data for teleport. 366 IAssetService cache = m_scene.AssetService;
388 // Only makes sense if there's a bake module and a cache module 367 IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
389 if (bakedModule != null && cache != null) 368
369 int validDirtyBakes = 0;
370 int hits = 0;
371
372 // our main cacheIDs mapper is p.Appearance.WearableCacheItems
373 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
374
375 if (wearableCache == null)
376 {
377 wearableCache = WearableCacheItem.GetDefaultCacheItem();
378 }
379
380 List<UUID> missing = new List<UUID>();
381
382 // Process received baked textures
383 for (int i = 0; i < cacheItems.Length; i++)
390 { 384 {
391 try 385 int idx = (int)cacheItems[i].TextureIndex;
386 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
387
388 // No face
389 if (face == null)
392 { 390 {
393 wearableCache = bakedModule.Get(sp.UUID); 391 // for some reason viewer is cleaning this
392 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx);
393 sp.Appearance.Texture.FaceTextures[idx].TextureID = AppearanceManager.DEFAULT_AVATAR_TEXTURE;
394 wearableCache[idx].CacheId = UUID.Zero;
395 wearableCache[idx].TextureID = UUID.Zero;
396 wearableCache[idx].TextureAsset = null;
397 continue;
394 } 398 }
395 catch (Exception) 399 else
396 { 400 {
401 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
402 {
403 wearableCache[idx].CacheId = UUID.Zero;
404 wearableCache[idx].TextureID = UUID.Zero;
405 wearableCache[idx].TextureAsset = null;
406 continue;
407 }
397 408
398 } 409/*
399 if (wearableCache != null) 410 if (face.TextureID == wearableCache[idx].TextureID && m_BakedTextureModule != null)
400 {
401 for (int i = 0; i < wearableCache.Length; i++)
402 { 411 {
403 cache.Cache(wearableCache[i].TextureAsset); 412 if (wearableCache[idx].CacheId != cacheItems[i].CacheId)
413 {
414 wearableCache[idx].CacheId = cacheItems[i].CacheId;
415 validDirtyBakes++;
416
417 //assuming this can only happen if asset is in cache
418 }
419 hits++;
420 continue;
421 }
422*/
423 wearableCache[idx].TextureAsset = null;
424 if (cache != null)
425 wearableCache[idx].TextureAsset = cache.GetCached(face.TextureID.ToString());
426
427 if (wearableCache[idx].TextureAsset != null)
428 {
429 if ( wearableCache[idx].TextureID != face.TextureID ||
430 wearableCache[idx].CacheId != cacheItems[i].CacheId)
431 validDirtyBakes++;
432
433 wearableCache[idx].TextureID = face.TextureID;
434 wearableCache[idx].CacheId = cacheItems[i].CacheId;
435 hits++;
436 }
437 else
438 {
439 wearableCache[idx].CacheId = UUID.Zero;
440 wearableCache[idx].TextureID = UUID.Zero;
441 wearableCache[idx].TextureAsset = null;
442 missing.Add(face.TextureID);
443 continue;
404 } 444 }
405 } 445 }
406 } 446 }
407 /* 447
408 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>(); 448 sp.Appearance.WearableCacheItems = wearableCache;
409 if (invService.GetRootFolder(userID) != null) 449
450 if (missing.Count > 0)
410 { 451 {
411 WearableCacheItem[] wearableCache = null; 452 foreach (UUID id in missing)
412 if (bakedModule != null) 453 sp.ControllingClient.SendRebakeAvatarTextures(id);
454 }
455
456 if (validDirtyBakes > 0 && hits == cacheItems.Length)
457 {
458 // if we got a full set of baked textures save all in BakedTextureModule
459 if (m_BakedTextureModule != null)
413 { 460 {
414 try 461 m_log.Debug("[UpdateBakedCache] uploading to bakedModule cache");
462
463 m_BakedTextureModule.Store(sp.UUID, wearableCache);
464 }
465 }
466
467
468 // debug
469 m_log.Debug("[UpdateBakedCache] cache hits: " + hits.ToString() + " changed entries: " + validDirtyBakes.ToString() + " rebakes " + missing.Count);
470/*
471 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
472 {
473 int j = AvatarAppearance.BAKE_INDICES[iter];
474 m_log.Debug("[UpdateBCache] {" + iter + "/" +
475 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
476 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
477 sp.Appearance.WearableCacheItems[j].TextureID);
478 }
479*/
480 return (hits == cacheItems.Length);
481 }
482
483 // called when we get a new root avatar
484 public bool ValidateBakedTextureCache(IScenePresence sp)
485 {
486 int hits = 0;
487
488 if (((ScenePresence)sp).isNPC)
489 return true;
490
491 lock (m_setAppearanceLock)
492 {
493 IAssetService cache = m_scene.AssetService;
494 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
495 WearableCacheItem[] bakedModuleCache = null;
496
497 if (cache == null)
498 return false;
499
500 WearableCacheItem[] wearableCache = sp.Appearance.WearableCacheItems;
501
502 // big debug
503 m_log.DebugFormat("[AVFACTORY]: ValidateBakedTextureCache start for {0} {1}", sp.Name, sp.UUID);
504/*
505 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
506 {
507 int j = AvatarAppearance.BAKE_INDICES[iter];
508 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[j];
509 if (wearableCache == null)
510 {
511 if (face != null)
512 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- " + face.TextureID);
513 else
514 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t- No texture");
515 }
516 else
517 {
518 if (face != null)
519 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " ft- " + face.TextureID +
520 "}: cc-" +
521 wearableCache[j].CacheId + ", ct-" +
522 wearableCache[j].TextureID
523 );
524 else
525 m_log.Debug("[ValidateBakedCache] {" + iter + "/" + j + " t - No texture" +
526 "}: cc-" +
527 wearableCache[j].CacheId + ", ct-" +
528 wearableCache[j].TextureID
529 );
530 }
531 }
532*/
533 bool wearableCacheValid = false;
534 if (wearableCache == null)
535 {
536 wearableCache = WearableCacheItem.GetDefaultCacheItem();
537 }
538 else
539 {
540 // we may have received a full cache
541 // check same coerence and store
542 wearableCacheValid = true;
543 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
415 { 544 {
416 wearableCache = bakedModule.Get(userID); 545 int idx = AvatarAppearance.BAKE_INDICES[i];
417 appearance.WearableCacheItems = wearableCache; 546 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
418 appearance.WearableCacheItemsDirty = false; 547 if (face != null)
419 foreach (WearableCacheItem item in wearableCache)
420 { 548 {
421 appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; 549 if (face.TextureID == wearableCache[idx].TextureID &&
550 face.TextureID != UUID.Zero)
551 {
552 if (wearableCache[idx].TextureAsset != null)
553 {
554 hits++;
555 wearableCache[idx].TextureAsset.Temporary = true;
556 wearableCache[idx].TextureAsset.Local = true;
557 cache.Store(wearableCache[idx].TextureAsset);
558 continue;
559 }
560 if (cache.GetCached((wearableCache[idx].TextureID).ToString()) != null)
561 {
562 hits++;
563 continue;
564 }
565 }
566 wearableCacheValid = false;
422 } 567 }
423 } 568 }
424 catch (Exception) 569
570 wearableCacheValid = (wearableCacheValid && (hits >= AvatarAppearance.BAKE_INDICES.Length - 1));
571 if (wearableCacheValid)
572 m_log.Debug("[ValidateBakedCache] have valid local cache");
573 }
574
575 bool checkExternal = false;
576
577 if (!wearableCacheValid)
578 {
579 // only use external bake module on login condition check
580// ScenePresence ssp = null;
581// if (sp is ScenePresence)
425 { 582 {
426 583// ssp = (ScenePresence)sp;
584// checkExternal = (((uint)ssp.TeleportFlags & (uint)TeleportFlags.ViaLogin) != 0) &&
585// bakedModule != null;
586
587 // or do it anytime we dont have the cache
588 checkExternal = bakedModule != null;
427 } 589 }
428 } 590 }
429 */
430 591
431 // Process the texture entry 592 if (checkExternal)
432 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
433 {
434 int idx = AvatarAppearance.BAKE_INDICES[i];
435 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
436
437 // No face, so lets check our baked service cache, teleport or login.
438 if (face == null)
439 { 593 {
440 if (wearableCache != null) 594 hits = 0;
595 bool gotbacked = false;
596
597 m_log.Debug("[ValidateBakedCache] local cache invalid, checking bakedModule");
598 try
599 {
600 bakedModuleCache = bakedModule.Get(sp.UUID);
601 }
602 catch (Exception e)
441 { 603 {
442 // If we find the an appearance item, set it as the textureentry and the face 604 m_log.ErrorFormat(e.ToString());
443 WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); 605 bakedModuleCache = null;
444 if (searchitem != null) 606 }
607
608 if (bakedModuleCache != null)
609 {
610 m_log.Debug("[ValidateBakedCache] got bakedModule " + bakedModuleCache.Length + " cached textures");
611
612 for (int i = 0; i < bakedModuleCache.Length; i++)
445 { 613 {
446 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); 614 int j = (int)bakedModuleCache[i].TextureIndex;
447 sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; 615
448 face = sp.Appearance.Texture.FaceTextures[idx]; 616 if (bakedModuleCache[i].TextureAsset != null)
617 {
618 wearableCache[j].TextureID = bakedModuleCache[i].TextureID;
619 wearableCache[j].CacheId = bakedModuleCache[i].CacheId;
620 wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset;
621 bakedModuleCache[i].TextureAsset.Temporary = true;
622 bakedModuleCache[i].TextureAsset.Local = true;
623 cache.Store(bakedModuleCache[i].TextureAsset);
624 }
449 } 625 }
450 else 626 gotbacked = true;
627 }
628
629 if (gotbacked)
630 {
631 // force the ones we got
632 for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
451 { 633 {
452 // if there is no texture entry and no baked cache, skip it 634 int idx = AvatarAppearance.BAKE_INDICES[i];
635 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx];
636
637 if (sp.Appearance.Texture.FaceTextures[idx] == null)
638 sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint)idx);
639 sp.Appearance.Texture.FaceTextures[idx].TextureID = wearableCache[idx].TextureID;
640 face = sp.Appearance.Texture.FaceTextures[idx];
641
642 // this should be removed
643 if (face.TextureID != UUID.Zero && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
644 hits++;
453 continue; 645 continue;
454 } 646 }
455 } 647 }
456 else
457 {
458 //No texture entry face and no cache. Skip this face.
459 continue;
460 }
461 } 648 }
462
463// m_log.DebugFormat(
464// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
465// face.TextureID, idx, client.Name, client.AgentId);
466 649
467 // if the texture is one of the "defaults" then skip it 650 sp.Appearance.WearableCacheItems = wearableCache;
468 // this should probably be more intelligent (skirt texture doesnt matter
469 // if the avatar isnt wearing a skirt) but if any of the main baked
470 // textures is default then the rest should be as well
471 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
472 continue;
473
474 defonly = false; // found a non-default texture reference
475 651
476 if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
477 return false;
478 } 652 }
479 653
480// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); 654 // debug
481 655 m_log.DebugFormat("[ValidateBakedCache]: Completed texture check for {0} {1} with {2} hits", sp.Name, sp.UUID, hits);
482 // If we only found default textures, then the appearance is not cached 656/*
483 return (defonly ? false : true); 657 for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++)
658 {
659 int j = AvatarAppearance.BAKE_INDICES[iter];
660 m_log.Debug("[ValidateBakedCache] {" + iter + "/" +
661 sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" +
662 sp.Appearance.WearableCacheItems[j].CacheId + ", t-" +
663 sp.Appearance.WearableCacheItems[j].TextureID);
664 }
665*/
666 return (hits >= AvatarAppearance.BAKE_INDICES.Length - 1); // skirt is optional
484 } 667 }
485 668
486 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) 669 public int RequestRebake(IScenePresence sp, bool missingTexturesOnly)
487 { 670 {
671 if (((ScenePresence)sp).isNPC)
672 return 0;
673
488 int texturesRebaked = 0; 674 int texturesRebaked = 0;
489// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>(); 675// IImprovedAssetCache cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
490 676
@@ -497,14 +683,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
497 if (face == null) 683 if (face == null)
498 continue; 684 continue;
499 685
500// m_log.DebugFormat(
501// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}",
502// face.TextureID, idx, client.Name, client.AgentId);
503
504 // if the texture is one of the "defaults" then skip it
505 // this should probably be more intelligent (skirt texture doesnt matter
506 // if the avatar isnt wearing a skirt) but if any of the main baked
507 // textures is default then the rest should be as well
508 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) 686 if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE)
509 continue; 687 continue;
510 688
@@ -675,7 +853,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
675 853
676 if (invService.GetRootFolder(userID) != null) 854 if (invService.GetRootFolder(userID) != null)
677 { 855 {
678 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 856 for (int i = 0; i < appearance.Wearables.Length; i++)
679 { 857 {
680 for (int j = 0; j < appearance.Wearables[i].Count; j++) 858 for (int j = 0; j < appearance.Wearables[i].Count; j++)
681 { 859 {
@@ -1080,8 +1258,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1080 1258
1081 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) 1259 foreach (AvatarWearingArgs.Wearable wear in e.NowWearing)
1082 { 1260 {
1083 if (wear.Type < AvatarWearable.MAX_WEARABLES) 1261 // If the wearable type is larger than the current array, expand it
1084 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero); 1262 if (avatAppearance.Wearables.Length <= wear.Type)
1263 {
1264 int currentLength = avatAppearance.Wearables.Length;
1265 AvatarWearable[] wears = avatAppearance.Wearables;
1266 Array.Resize(ref wears, wear.Type + 1);
1267 for (int i = currentLength ; i <= wear.Type ; i++)
1268 wears[i] = new AvatarWearable();
1269 avatAppearance.Wearables = wears;
1270 }
1271 avatAppearance.Wearables[wear.Type].Add(wear.ItemID, UUID.Zero);
1085 } 1272 }
1086 1273
1087 avatAppearance.GetAssetsFrom(sp.Appearance); 1274 avatAppearance.GetAssetsFrom(sp.Appearance);
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 9513408..dd93449 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
181 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); 181 Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex);
182 eyesFace.TextureID = eyesTextureId; 182 eyesFace.TextureID = eyesTextureId;
183 183
184 afm.SetAppearance(sp, bakedTextureEntry, visualParams, null); 184 afm.SetAppearance(sp, bakedTextureEntry, visualParams, new WearableCacheItem[0]);
185 afm.SaveBakedTextures(userId); 185 afm.SaveBakedTextures(userId);
186// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId); 186// Dictionary<BakeType, Primitive.TextureEntryFace> bakedTextures = afm.GetBakedTextureFaces(userId);
187 187
diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
index 414f06a..c0686d9 100644
--- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
@@ -101,8 +101,6 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
101 if (m_URL == String.Empty) 101 if (m_URL == String.Empty)
102 return null; 102 return null;
103 103
104 int size = 0;
105
106 using (RestClient rc = new RestClient(m_URL)) 104 using (RestClient rc = new RestClient(m_URL))
107 { 105 {
108 List<WearableCacheItem> ret = new List<WearableCacheItem>(); 106 List<WearableCacheItem> ret = new List<WearableCacheItem>();
@@ -113,35 +111,34 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
113 111
114 try 112 try
115 { 113 {
116 Stream s = rc.Request(m_Auth); 114 using(Stream s = rc.Request(m_Auth))
117
118 using (XmlTextReader sr = new XmlTextReader(s))
119 { 115 {
120 sr.ReadStartElement("BakedAppearance"); 116 using(XmlTextReader sr = new XmlTextReader(s))
121 while (sr.LocalName == "BakedTexture")
122 { 117 {
123 string sTextureIndex = sr.GetAttribute("TextureIndex"); 118 sr.ReadStartElement("BakedAppearance");
124 int lTextureIndex = Convert.ToInt32(sTextureIndex); 119 while(sr.LocalName == "BakedTexture")
125 string sCacheId = sr.GetAttribute("CacheId");
126 UUID lCacheId = UUID.Zero;
127 if (!(UUID.TryParse(sCacheId, out lCacheId)))
128 { 120 {
121 string sTextureIndex = sr.GetAttribute("TextureIndex");
122 int lTextureIndex = Convert.ToInt32(sTextureIndex);
123 string sCacheId = sr.GetAttribute("CacheId");
124 UUID lCacheId = UUID.Zero;
125 if(!(UUID.TryParse(sCacheId,out lCacheId)))
126 {
129 // ?? Nothing here 127 // ?? Nothing here
128 }
129
130 sr.ReadStartElement("BakedTexture");
131 if(sr.Name=="AssetBase")
132 {
133 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
134 ret.Add(new WearableCacheItem() { CacheId = lCacheId,TextureIndex = (uint)lTextureIndex,TextureAsset = a,TextureID = a.FullID });
135 sr.ReadEndElement();
136 }
130 } 137 }
131 138 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}",ret.Count,id);
132 ++size;
133
134 sr.ReadStartElement("BakedTexture");
135 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
136 ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID });
137
138 sr.ReadEndElement();
139 } 139 }
140 140 return ret.ToArray();
141 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
142 } 141 }
143
144 return ret.ToArray();
145 } 142 }
146 catch (XmlException) 143 catch (XmlException)
147 { 144 {
@@ -150,13 +147,22 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
150 } 147 }
151 } 148 }
152 149
150 public void Store(UUID agentId)
151 {
152 }
153
154 public void UpdateMeshAvatar(UUID agentId)
155 {
156 }
157
153 public void Store(UUID agentId, WearableCacheItem[] data) 158 public void Store(UUID agentId, WearableCacheItem[] data)
154 { 159 {
155 if (m_URL == String.Empty) 160 if (m_URL == String.Empty)
156 return; 161 return;
157 162
163 int numberWears = 0;
158 MemoryStream reqStream; 164 MemoryStream reqStream;
159 165
160 using (MemoryStream bakeStream = new MemoryStream()) 166 using (MemoryStream bakeStream = new MemoryStream())
161 using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null)) 167 using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null))
162 { 168 {
@@ -164,15 +170,16 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
164 170
165 for (int i = 0; i < data.Length; i++) 171 for (int i = 0; i < data.Length; i++)
166 { 172 {
167 if (data[i] != null) 173 if (data[i] != null && data[i].TextureAsset != null)
168 { 174 {
169 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty); 175 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
170 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString()); 176 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
171 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString()); 177 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
172 if (data[i].TextureAsset != null) 178// if (data[i].TextureAsset != null)
173 m_serializer.Serialize(bakeWriter, data[i].TextureAsset); 179 m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
174 180
175 bakeWriter.WriteEndElement(); 181 bakeWriter.WriteEndElement();
182 numberWears++;
176 } 183 }
177 } 184 }
178 185
@@ -182,17 +189,18 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
182 reqStream = new MemoryStream(bakeStream.ToArray()); 189 reqStream = new MemoryStream(bakeStream.ToArray());
183 } 190 }
184 191
185 RestClient rc = new RestClient(m_URL);
186 rc.AddResourcePath("bakes");
187 rc.AddResourcePath(agentId.ToString());
188
189 rc.RequestMethod = "POST";
190
191 Util.FireAndForget( 192 Util.FireAndForget(
192 delegate 193 delegate
193 { 194 {
194 rc.Request(reqStream, m_Auth); 195 using(RestClient rc = new RestClient(m_URL))
195 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", data.Length, agentId); 196 {
197 rc.AddResourcePath("bakes");
198 rc.AddResourcePath(agentId.ToString());
199 rc.RequestMethod = "POST";
200
201 rc.Request(reqStream, m_Auth);
202 m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", numberWears, agentId);
203 }
196 }, null, "XBakesModule.Store" 204 }, null, "XBakesModule.Store"
197 ); 205 );
198 } 206 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index f0b1e67..d83713b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -51,7 +51,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
51 private int m_saydistance = 20; 51 private int m_saydistance = 20;
52 private int m_shoutdistance = 100; 52 private int m_shoutdistance = 100;
53 private int m_whisperdistance = 10; 53 private int m_whisperdistance = 10;
54 54 private List<Scene> m_scenes = new List<Scene>();
55 private List<string> FreezeCache = new List<string>();
56 private string m_adminPrefix = "";
55 internal object m_syncy = new object(); 57 internal object m_syncy = new object();
56 58
57 internal IConfig m_config; 59 internal IConfig m_config;
@@ -69,21 +71,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
69 m_enabled = false; 71 m_enabled = false;
70 return; 72 return;
71 } 73 }
74
75 m_whisperdistance = m_config.GetInt("whisper_distance", m_whisperdistance);
76 m_saydistance = m_config.GetInt("say_distance", m_saydistance);
77 m_shoutdistance = m_config.GetInt("shout_distance", m_shoutdistance);
78 m_adminPrefix = m_config.GetString("admin_prefix", "");
72 } 79 }
73
74 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance);
75 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance);
76 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance);
77 } 80 }
78 81
79 public virtual void AddRegion(Scene scene) 82 public virtual void AddRegion(Scene scene)
80 { 83 {
81 if (!m_enabled) 84 if (!m_enabled) return;
82 return;
83 85
84 scene.EventManager.OnNewClient += OnNewClient; 86 lock (m_syncy)
85 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 87 {
86 scene.EventManager.OnChatBroadcast += OnChatBroadcast; 88 if (!m_scenes.Contains(scene))
89 {
90 m_scenes.Add(scene);
91 scene.EventManager.OnNewClient += OnNewClient;
92 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
93 scene.EventManager.OnChatBroadcast += OnChatBroadcast;
94 }
95 }
87 96
88 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, 97 m_log.InfoFormat("[CHAT]: Initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName,
89 m_whisperdistance, m_saydistance, m_shoutdistance); 98 m_whisperdistance, m_saydistance, m_shoutdistance);
@@ -103,12 +112,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 112
104 public virtual void RemoveRegion(Scene scene) 113 public virtual void RemoveRegion(Scene scene)
105 { 114 {
106 if (!m_enabled) 115 if (!m_enabled) return;
107 return;
108 116
109 scene.EventManager.OnNewClient -= OnNewClient; 117 lock (m_syncy)
110 scene.EventManager.OnChatFromWorld -= OnChatFromWorld; 118 {
111 scene.EventManager.OnChatBroadcast -= OnChatBroadcast; 119 if (m_scenes.Contains(scene))
120 {
121 scene.EventManager.OnNewClient -= OnNewClient;
122 scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
123 scene.EventManager.OnChatBroadcast -= OnChatBroadcast;
124 m_scenes.Remove(scene);
125 }
126 }
112 } 127 }
113 128
114 public virtual void Close() 129 public virtual void Close()
@@ -165,7 +180,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
165 return; 180 return;
166 } 181 }
167 182
168 DeliverChatToAvatars(ChatSourceType.Agent, c); 183 if (FreezeCache.Contains(c.Sender.AgentId.ToString()))
184 {
185 if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping)
186 c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false);
187 }
188 else
189 {
190 DeliverChatToAvatars(ChatSourceType.Agent, c);
191 }
169 } 192 }
170 193
171 public virtual void OnChatFromWorld(Object sender, OSChatMessage c) 194 public virtual void OnChatFromWorld(Object sender, OSChatMessage c)
@@ -179,33 +202,61 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
179 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) 202 protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c)
180 { 203 {
181 string fromName = c.From; 204 string fromName = c.From;
205 string fromNamePrefix = "";
182 UUID fromID = UUID.Zero; 206 UUID fromID = UUID.Zero;
183 UUID ownerID = UUID.Zero; 207 UUID ownerID = UUID.Zero;
184 UUID targetID = c.TargetUUID;
185 string message = c.Message; 208 string message = c.Message;
186 Scene scene = (Scene)c.Scene; 209 IScene scene = c.Scene;
210 UUID destination = c.Destination;
187 Vector3 fromPos = c.Position; 211 Vector3 fromPos = c.Position;
188 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0); 212 Vector3 regionPos = new Vector3(scene.RegionInfo.WorldLocX, scene.RegionInfo.WorldLocY, 0);
189 213
214 bool checkParcelHide = false;
215 UUID sourceParcelID = UUID.Zero;
216 Vector3 hidePos = fromPos;
217
190 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; 218 if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel;
191 219
192 switch (sourceType) 220 switch (sourceType)
193 { 221 {
194 case ChatSourceType.Agent: 222 case ChatSourceType.Agent:
195 ScenePresence avatar = scene.GetScenePresence(c.Sender.AgentId); 223 if (!(scene is Scene))
224 {
225 m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}",
226 scene.RegionInfo.RegionName, c.Sender.AgentId);
227 return;
228 }
229 ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId);
196 fromPos = avatar.AbsolutePosition; 230 fromPos = avatar.AbsolutePosition;
197 fromName = avatar.Name; 231 fromName = avatar.Name;
198 fromID = c.Sender.AgentId; 232 fromID = c.Sender.AgentId;
233 if (avatar.GodLevel >= 200)
234 { // let gods speak to outside or things may get confusing
235 fromNamePrefix = m_adminPrefix;
236 checkParcelHide = false;
237 }
238 else
239 {
240 checkParcelHide = true;
241 }
242 destination = UUID.Zero; // Avatars cant "SayTo"
199 ownerID = c.Sender.AgentId; 243 ownerID = c.Sender.AgentId;
200 244
245 hidePos = fromPos;
201 break; 246 break;
202 247
203 case ChatSourceType.Object: 248 case ChatSourceType.Object:
204 fromID = c.SenderUUID; 249 fromID = c.SenderUUID;
205 250
206 if (c.SenderObject != null && c.SenderObject is SceneObjectPart) 251 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
252 {
207 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; 253 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
208 254 if (((SceneObjectPart)c.SenderObject).ParentGroup.IsAttachment)
255 {
256 checkParcelHide = true;
257 hidePos = ((SceneObjectPart)c.SenderObject).ParentGroup.AbsolutePosition;
258 }
259 }
209 break; 260 break;
210 } 261 }
211 262
@@ -214,38 +265,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
214 message = message.Substring(0, 1000); 265 message = message.Substring(0, 1000);
215 266
216// m_log.DebugFormat( 267// m_log.DebugFormat(
217// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}, targetID {5}", 268// "[CHAT]: DCTA: fromID {0} fromName {1}, region{2}, cType {3}, sType {4}",
218// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType, targetID); 269// fromID, fromName, scene.RegionInfo.RegionName, c.Type, sourceType);
219 270
220 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 271 HashSet<UUID> receiverIDs = new HashSet<UUID>();
221 272
222 if (targetID == UUID.Zero) 273 if (checkParcelHide)
274 {
275 checkParcelHide = false;
276 if (c.Type < ChatTypeEnum.DebugChannel && destination == UUID.Zero)
277 {
278 ILandObject srcland = (scene as Scene).LandChannel.GetLandObject(hidePos.X, hidePos.Y);
279 if (srcland != null && !srcland.LandData.SeeAVs)
280 {
281 sourceParcelID = srcland.LandData.GlobalID;
282 checkParcelHide = true;
283 }
284 }
285 }
286
287 foreach (Scene s in m_scenes)
223 { 288 {
224 // This should use ForEachClient, but clients don't have a position. 289 // This should use ForEachClient, but clients don't have a position.
225 // If camera is moved into client, then camera position can be used 290 // If camera is moved into client, then camera position can be used
226 scene.ForEachScenePresence( 291 // MT: No, it can't, as chat is heard from the avatar position, not
292 // the camera position.
293
294 s.ForEachScenePresence(
227 delegate(ScenePresence presence) 295 delegate(ScenePresence presence)
228 { 296 {
229 if (TrySendChatMessage( 297 if (destination != UUID.Zero && presence.UUID != destination)
230 presence, fromPos, regionPos, fromID, ownerID, fromName, c.Type, message, sourceType, false)) 298 return;
231 receiverIDs.Add(presence.UUID); 299 ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
300 if (Presencecheck != null)
301 {
302 // This will pass all chat from objects. Not
303 // perfect, but it will do. For now. Better
304 // than the prior behavior of muting all
305 // objects on a parcel with access restrictions
306 if (checkParcelHide)
307 {
308 if (sourceParcelID != Presencecheck.LandData.GlobalID && presence.GodLevel < 200)
309 return;
310 }
311 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
312 {
313 if (destination != UUID.Zero)
314 {
315 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
316 receiverIDs.Add(presence.UUID);
317 }
318 else
319 {
320 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
321 receiverIDs.Add(presence.UUID);
322 }
323 }
324 }
232 } 325 }
233 ); 326 );
234 } 327 }
235 else 328
236 { 329 (scene as Scene).EventManager.TriggerOnChatToClients(
237 // This is a send to a specific client eg from llRegionSayTo
238 // no need to check distance etc, jand send is as say
239 ScenePresence presence = scene.GetScenePresence(targetID);
240 if (presence != null && !presence.IsChildAgent)
241 {
242 if (TrySendChatMessage(
243 presence, fromPos, regionPos, fromID, ownerID, fromName, ChatTypeEnum.Say, message, sourceType, true))
244 receiverIDs.Add(presence.UUID);
245 }
246 }
247
248 scene.EventManager.TriggerOnChatToClients(
249 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully); 330 fromID, receiverIDs, message, c.Type, fromPos, fromName, sourceType, ChatAudibleLevel.Fully);
250 } 331 }
251 332
@@ -287,28 +368,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
287 } 368 }
288 369
289 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); 370 // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType);
290
291 HashSet<UUID> receiverIDs = new HashSet<UUID>(); 371 HashSet<UUID> receiverIDs = new HashSet<UUID>();
292 372
293 ((Scene)c.Scene).ForEachRootClient( 373 if (c.Scene != null)
294 delegate(IClientAPI client) 374 {
295 { 375 ((Scene)c.Scene).ForEachRootClient
296 // don't forward SayOwner chat from objects to 376 (
297 // non-owner agents 377 delegate(IClientAPI client)
298 if ((c.Type == ChatTypeEnum.Owner) && 378 {
299 (null != c.SenderObject) && 379 // don't forward SayOwner chat from objects to
300 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 380 // non-owner agents
301 return; 381 if ((c.Type == ChatTypeEnum.Owner) &&
302 382 (null != c.SenderObject) &&
303 client.SendChatMessage( 383 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
304 c.Message, (byte)cType, CenterOfRegion, fromName, fromID, ownerID, 384 return;
305 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 385
306 386 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
307 receiverIDs.Add(client.AgentId); 387 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
308 }); 388 receiverIDs.Add(client.AgentId);
309 389 }
310 (c.Scene as Scene).EventManager.TriggerOnChatToClients( 390 );
311 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully); 391 (c.Scene as Scene).EventManager.TriggerOnChatToClients(
392 fromID, receiverIDs, c.Message, cType, CenterOfRegion, fromName, sourceType, ChatAudibleLevel.Fully);
393 }
312 } 394 }
313 395
314 /// <summary> 396 /// <summary>
@@ -360,6 +442,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
360 return true; 442 return true;
361 } 443 }
362 444
445 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
446 public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
447 {
448 System.Threading.Timer Timer;
449 if (flags == 0)
450 {
451 FreezeCache.Add(target.ToString());
452 System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen);
453 Timer = new System.Threading.Timer(timeCB, target, 30000, 0);
454 Timers.Add(target, Timer);
455 }
456 else
457 {
458 FreezeCache.Remove(target.ToString());
459 Timers.TryGetValue(target, out Timer);
460 Timers.Remove(target);
461 Timer.Dispose();
462 }
463 }
464
465 private void OnEndParcelFrozen(object avatar)
466 {
467 UUID target = (UUID)avatar;
468 FreezeCache.Remove(target.ToString());
469 System.Threading.Timer Timer;
470 Timers.TryGetValue(target, out Timer);
471 Timers.Remove(target);
472 Timer.Dispose();
473 }
363 #region SimulatorFeaturesRequest 474 #region SimulatorFeaturesRequest
364 475
365 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange; 476 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index fc23b72..4e1958a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -183,10 +183,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
183 try 183 try
184 { 184 {
185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 185 ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
186
187 if (obj == null) 186 if (obj == null)
188 return; 187 return;
189
190 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0 188 if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0
191 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage) 189 || avatar.Scene.RegionInfo.RegionSettings.AllowDamage)
192 { 190 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index a896897..56819fa 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -203,8 +203,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
203 { 203 {
204 m_scene.ForEachRootClient(delegate(IClientAPI client) 204 m_scene.ForEachRootClient(delegate(IClientAPI client)
205 { 205 {
206 client.SendBlueBoxMessage(fromAvatarID, fromAvatarName, 206 client.SendAgentAlertMessage(
207 message); 207 message, false);
208 }); 208 });
209 } 209 }
210 210
@@ -260,4 +260,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
260 return result; 260 return result;
261 } 261 }
262 } 262 }
263} \ No newline at end of file 263}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 08e7dd2..d6c4d5b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -262,6 +262,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
262 client.OnDenyFriendRequest += OnDenyFriendRequest; 262 client.OnDenyFriendRequest += OnDenyFriendRequest;
263 client.OnTerminateFriendship += RemoveFriendship; 263 client.OnTerminateFriendship += RemoveFriendship;
264 client.OnGrantUserRights += GrantRights; 264 client.OnGrantUserRights += GrantRights;
265 client.OnFindAgent += FindFriend;
265 266
266 // We need to cache information for child agents as well as root agents so that friend edit/move/delete 267 // We need to cache information for child agents as well as root agents so that friend edit/move/delete
267 // permissions will work across borders where both regions are on different simulators. 268 // permissions will work across borders where both regions are on different simulators.
@@ -726,6 +727,64 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
726 } 727 }
727 } 728 }
728 729
730 public void FindFriend(IClientAPI remoteClient,UUID HunterID ,UUID PreyID)
731 {
732 UUID requester = remoteClient.AgentId;
733 if(requester != HunterID) // only allow client agent to be the hunter (?)
734 return;
735
736 FriendInfo[] friends = GetFriendsFromCache(requester);
737 if (friends.Length == 0)
738 return;
739
740 FriendInfo friend = GetFriend(friends, PreyID);
741 if (friend == null)
742 return;
743
744 if((friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0)
745 return;
746
747 Scene hunterScene = (Scene)remoteClient.Scene;
748
749 if(hunterScene == null)
750 return;
751
752 // check local
753 ScenePresence sp;
754 double px;
755 double py;
756 if(hunterScene.TryGetScenePresence(PreyID, out sp))
757 {
758 if(sp == null)
759 return;
760 px = hunterScene.RegionInfo.WorldLocX + sp.AbsolutePosition.X;
761 py = hunterScene.RegionInfo.WorldLocY + sp.AbsolutePosition.Y;
762
763 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
764 return;
765 }
766
767 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { PreyID.ToString() });
768
769 if (friendSessions == null || friendSessions.Length == 0)
770 return;
771
772 PresenceInfo friendSession = friendSessions[0];
773 if (friendSession == null)
774 return;
775
776 GridRegion region = GridService.GetRegionByUUID(hunterScene.RegionInfo.ScopeID, friendSession.RegionID);
777
778 if(region == null)
779 return;
780
781 // we don't have presence location so point to a standard region center for now
782 px = region.RegionLocX + 128.0;
783 py = region.RegionLocY + 128.0;
784
785 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
786 }
787
729 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights) 788 public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights)
730 { 789 {
731 UUID requester = remoteClient.AgentId; 790 UUID requester = remoteClient.AgentId;
@@ -745,7 +804,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
745 804
746 if (friend != null) // Found it 805 if (friend != null) // Found it
747 { 806 {
748 // Store it on the DB 807 // Store it on service
749 if (!StoreRights(requester, friendID, rights)) 808 if (!StoreRights(requester, friendID, rights))
750 { 809 {
751 remoteClient.SendAlertMessage("Unable to grant rights."); 810 remoteClient.SendAlertMessage("Unable to grant rights.");
@@ -869,28 +928,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
869 return false; 928 return false;
870 } 929 }
871 930
872 public bool LocalGrantRights(UUID userID, UUID friendID, int userFlags, int rights) 931 public bool LocalGrantRights(UUID userID, UUID friendID, int oldRights, int newRights)
873 { 932 {
874 IClientAPI friendClient = LocateClientObject(friendID); 933 IClientAPI friendClient = LocateClientObject(friendID);
875 if (friendClient != null) 934 if (friendClient != null)
876 { 935 {
877 bool onlineBitChanged = ((rights ^ userFlags) & (int)FriendRights.CanSeeOnline) != 0; 936 int changedRights = newRights ^ oldRights;
937 bool onlineBitChanged = (changedRights & (int)FriendRights.CanSeeOnline) != 0;
878 if (onlineBitChanged) 938 if (onlineBitChanged)
879 { 939 {
880 if ((rights & (int)FriendRights.CanSeeOnline) == 1) 940 if ((newRights & (int)FriendRights.CanSeeOnline) == 1)
881 friendClient.SendAgentOnline(new UUID[] { userID }); 941 friendClient.SendAgentOnline(new UUID[] { userID });
882 else 942 else
883 friendClient.SendAgentOffline(new UUID[] { userID }); 943 friendClient.SendAgentOffline(new UUID[] { userID });
884 } 944 }
885 else 945
886 { 946 if(changedRights != 0)
887 bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; 947 friendClient.SendChangeUserRights(userID, friendID, newRights);
888 if (canEditObjectsChanged)
889 friendClient.SendChangeUserRights(userID, friendID, rights);
890 }
891 948
892 // Update local cache 949 // Update local cache
893 UpdateLocalCache(userID, friendID, rights); 950 UpdateLocalCache(userID, friendID, newRights);
894 951
895 return true; 952 return true;
896 } 953 }
@@ -946,8 +1003,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
946 lock (m_Friends) 1003 lock (m_Friends)
947 { 1004 {
948 FriendInfo[] friends = GetFriendsFromCache(friendID); 1005 FriendInfo[] friends = GetFriendsFromCache(friendID);
949 FriendInfo finfo = GetFriend(friends, userID); 1006 if(friends != EMPTY_FRIENDS)
950 finfo.TheirFlags = rights; 1007 {
1008 FriendInfo finfo = GetFriend(friends, userID);
1009 if(finfo!= null)
1010 finfo.TheirFlags = rights;
1011 }
951 } 1012 }
952 } 1013 }
953 1014
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 13512a2..c421740 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -211,7 +211,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
211 { 211 {
212 UUID fromID = UUID.Zero; 212 UUID fromID = UUID.Zero;
213 UUID toID = UUID.Zero; 213 UUID toID = UUID.Zero;
214 int rights = 0, userFlags = 0; 214 int oldRights = 0, newRights = 0;
215 215
216 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) 216 if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID"))
217 return FailureResult(); 217 return FailureResult();
@@ -222,13 +222,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
222 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 222 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
223 return FailureResult(); 223 return FailureResult();
224 224
225 if (!Int32.TryParse(request["UserFlags"].ToString(), out userFlags)) 225 if (!Int32.TryParse(request["UserFlags"].ToString(), out oldRights))
226 return FailureResult(); 226 return FailureResult();
227 227
228 if (!Int32.TryParse(request["Rights"].ToString(), out rights)) 228 if (!Int32.TryParse(request["Rights"].ToString(), out newRights))
229 return FailureResult(); 229 return FailureResult();
230 230
231 if (m_FriendsModule.LocalGrantRights(UUID.Zero, UUID.Zero, userFlags, rights)) 231 if (m_FriendsModule.LocalGrantRights(fromID, toID, oldRights, newRights))
232 return SuccessResult(); 232 return SuccessResult();
233 233
234 return FailureResult(); 234 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 3b6d970..adb838c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -49,6 +49,8 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
49using OSDArray = OpenMetaverse.StructuredData.OSDArray; 49using OSDArray = OpenMetaverse.StructuredData.OSDArray;
50using OSDMap = OpenMetaverse.StructuredData.OSDMap; 50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
51 51
52using Mono.Addins;
53
52namespace OpenSim.Region.CoreModules.Avatar.Gods 54namespace OpenSim.Region.CoreModules.Avatar.Gods
53{ 55{
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")] 56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")]
@@ -62,6 +64,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
62 64
63 protected Scene m_scene; 65 protected Scene m_scene;
64 protected IDialogModule m_dialogModule; 66 protected IDialogModule m_dialogModule;
67
65 protected IDialogModule DialogModule 68 protected IDialogModule DialogModule
66 { 69 {
67 get 70 get
@@ -146,6 +149,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
146 UUID godSessionID = userData["GodSessionID"].AsUUID(); 149 UUID godSessionID = userData["GodSessionID"].AsUUID();
147 uint kickFlags = userData["KickFlags"].AsUInteger(); 150 uint kickFlags = userData["KickFlags"].AsUInteger();
148 string reason = userData["Reason"].AsString(); 151 string reason = userData["Reason"].AsString();
152
149 ScenePresence god = m_scene.GetScenePresence(godID); 153 ScenePresence god = m_scene.GetScenePresence(godID);
150 if (god == null || god.ControllingClient.SessionId != godSessionID) 154 if (god == null || god.ControllingClient.SessionId != godSessionID)
151 return String.Empty; 155 return String.Empty;
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index c33a296..55e30a0 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -27,6 +27,7 @@
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using System.Timers;
30using log4net; 31using log4net;
31using Mono.Addins; 32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
@@ -44,6 +45,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
44 private static readonly ILog m_log = LogManager.GetLogger( 45 private static readonly ILog m_log = LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType); 46 MethodBase.GetCurrentMethod().DeclaringType);
46 47
48 private Timer m_logTimer = new Timer(10000);
49 private List<GridInstantMessage> m_logData = new List<GridInstantMessage>();
50 private string m_restUrl;
51
47 /// <value> 52 /// <value>
48 /// Is this module enabled? 53 /// Is this module enabled?
49 /// </value> 54 /// </value>
@@ -63,9 +68,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
63 "InstantMessageModule", "InstantMessageModule") != 68 "InstantMessageModule", "InstantMessageModule") !=
64 "InstantMessageModule") 69 "InstantMessageModule")
65 return; 70 return;
71 m_restUrl = config.Configs["Messaging"].GetString("LogURL", String.Empty);
66 } 72 }
67 73
68 m_enabled = true; 74 m_enabled = true;
75 m_logTimer.AutoReset = false;
76 m_logTimer.Elapsed += LogTimerElapsed;
69 } 77 }
70 78
71 public void AddRegion(Scene scene) 79 public void AddRegion(Scene scene)
@@ -150,6 +158,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
150 { 158 {
151 byte dialog = im.dialog; 159 byte dialog = im.dialog;
152 160
161 if (client != null && dialog == (byte)InstantMessageDialog.MessageFromAgent)
162 LogInstantMesssage(im);
163
153 if (dialog != (byte)InstantMessageDialog.MessageFromAgent 164 if (dialog != (byte)InstantMessageDialog.MessageFromAgent
154 && dialog != (byte)InstantMessageDialog.StartTyping 165 && dialog != (byte)InstantMessageDialog.StartTyping
155 && dialog != (byte)InstantMessageDialog.StopTyping 166 && dialog != (byte)InstantMessageDialog.StopTyping
@@ -159,6 +170,32 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 return; 170 return;
160 } 171 }
161 172
173 //DateTime dt = DateTime.UtcNow;
174
175 // Ticks from UtcNow, but make it look like local. Evil, huh?
176 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
177
178 //try
179 //{
180 // // Convert that to the PST timezone
181 // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
182 // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
183 //}
184 //catch
185 //{
186 // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
187 //}
188
189 //// And make it look local again to fool the unix time util
190 //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
191
192 // If client is null, this message comes from storage and IS offline
193 if (client != null)
194 im.offline = 0;
195
196 if (im.offline == 0)
197 im.timestamp = (uint)Util.UnixTimeSinceEpoch();
198
162 if (m_TransferModule != null) 199 if (m_TransferModule != null)
163 { 200 {
164 if (client != null) 201 if (client != null)
@@ -202,5 +239,35 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
202 // 239 //
203 OnInstantMessage(null, msg); 240 OnInstantMessage(null, msg);
204 } 241 }
242
243 private void LogInstantMesssage(GridInstantMessage im)
244 {
245 if (m_logData.Count < 20)
246 {
247 // Restart the log write timer
248 m_logTimer.Stop();
249 }
250 if (!m_logTimer.Enabled)
251 m_logTimer.Start();
252
253 lock (m_logData)
254 {
255 m_logData.Add(im);
256 }
257 }
258
259 private void LogTimerElapsed(object source, ElapsedEventArgs e)
260 {
261 lock (m_logData)
262 {
263 if (m_restUrl != String.Empty && m_logData.Count > 0)
264 {
265 bool success = SynchronousRestObjectRequester.MakeRequest<List<GridInstantMessage>, bool>("POST", m_restUrl + "/LogMessages/", m_logData);
266 if (!success)
267 m_log.ErrorFormat("[INSTANT MESSAGE]: Failed to save log data");
268 }
269 m_logData.Clear();
270 }
271 }
205 } 272 }
206} 273}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 2462ff8..3c82fd9 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 51
52 private bool m_Enabled = false; 52 private bool m_Enabled = false;
53 protected string m_MessageKey = String.Empty;
53 protected List<Scene> m_Scenes = new List<Scene>(); 54 protected List<Scene> m_Scenes = new List<Scene>();
54 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>(); 55 protected Dictionary<UUID, UUID> m_UserRegionMap = new Dictionary<UUID, UUID>();
55 56
@@ -69,14 +70,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
69 public virtual void Initialise(IConfigSource config) 70 public virtual void Initialise(IConfigSource config)
70 { 71 {
71 IConfig cnf = config.Configs["Messaging"]; 72 IConfig cnf = config.Configs["Messaging"];
72 if (cnf != null && cnf.GetString( 73 if (cnf != null)
73 "MessageTransferModule", "MessageTransferModule") !=
74 "MessageTransferModule")
75 { 74 {
76 m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); 75 if (cnf.GetString("MessageTransferModule",
77 return; 76 "MessageTransferModule") != "MessageTransferModule")
78 } 77 {
78 return;
79 }
79 80
81 m_MessageKey = cnf.GetString("MessageKey", String.Empty);
82 }
83 m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
80 m_Enabled = true; 84 m_Enabled = true;
81 } 85 }
82 86
@@ -135,6 +139,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
135 { 139 {
136 UUID toAgentID = new UUID(im.toAgentID); 140 UUID toAgentID = new UUID(im.toAgentID);
137 141
142 if (toAgentID == UUID.Zero)
143 return;
144
138 // Try root avatar only first 145 // Try root avatar only first
139 foreach (Scene scene in m_Scenes) 146 foreach (Scene scene in m_Scenes)
140 { 147 {
@@ -181,7 +188,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
181 SendGridInstantMessageViaXMLRPC(im, result); 188 SendGridInstantMessageViaXMLRPC(im, result);
182 } 189 }
183 190
184 public void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result) 191 public virtual void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
185 { 192 {
186 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; 193 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
187 194
@@ -249,6 +256,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
249 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") 256 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
250 && requestData.ContainsKey("binary_bucket")) 257 && requestData.ContainsKey("binary_bucket"))
251 { 258 {
259 if (m_MessageKey != String.Empty)
260 {
261 XmlRpcResponse error_resp = new XmlRpcResponse();
262 Hashtable error_respdata = new Hashtable();
263 error_respdata["success"] = "FALSE";
264 error_resp.Value = error_respdata;
265
266 if (!requestData.Contains("message_key"))
267 return error_resp;
268 if (m_MessageKey != (string)requestData["message_key"])
269 return error_resp;
270 }
271
252 // Do the easy way of validating the UUIDs 272 // Do the easy way of validating the UUIDs
253 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); 273 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
254 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); 274 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -425,104 +445,192 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
425 return resp; 445 return resp;
426 } 446 }
427 447
448
428 /// <summary> 449 /// <summary>
429 /// delegate for sending a grid instant message asynchronously 450 /// delegate for sending a grid instant message asynchronously
430 /// </summary> 451 /// </summary>
431 public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); 452 private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
453
454 private class GIM {
455 public GridInstantMessage im;
456 public MessageResultNotification result;
457 };
458
459 private Queue<GIM> pendingInstantMessages = new Queue<GIM>();
460 private int numInstantMessageThreads = 0;
432 461
433 protected virtual void GridInstantMessageCompleted(IAsyncResult iar) 462 private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
434 { 463 {
435 GridInstantMessageDelegate icon = 464 lock (pendingInstantMessages) {
436 (GridInstantMessageDelegate)iar.AsyncState; 465 if (numInstantMessageThreads >= 4) {
437 icon.EndInvoke(iar); 466 GIM gim = new GIM();
467 gim.im = im;
468 gim.result = result;
469 pendingInstantMessages.Enqueue(gim);
470 } else {
471 ++ numInstantMessageThreads;
472 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
473 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
474 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
475 }
476 }
438 } 477 }
439 478
440 479
441 protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) 480 private void GridInstantMessageCompleted(IAsyncResult iar)
442 { 481 {
443 GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; 482 GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
444 483 d.EndInvoke(iar);
445 d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
446 } 484 }
447 485
448 /// <summary> 486 /// <summary>
449 /// Internal SendGridInstantMessage over XMLRPC method. 487 /// Internal SendGridInstantMessage over XMLRPC method.
450 /// </summary> 488 /// </summary>
451 /// <remarks> 489
452 /// This is called from within a dedicated thread. 490 /// <param name="prevRegionHandle">
453 /// </remarks> 491 /// Pass in 0 the first time this method is called. It will be called recursively with the last
454 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) 492 /// regionhandle tried
493 /// </param>
494 private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
455 { 495 {
496 GIM gim;
497 do {
498 try {
499 SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
500 } catch (Exception e) {
501 m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
502 }
503 lock (pendingInstantMessages) {
504 if (pendingInstantMessages.Count > 0) {
505 gim = pendingInstantMessages.Dequeue();
506 im = gim.im;
507 result = gim.result;
508 } else {
509 gim = null;
510 -- numInstantMessageThreads;
511 //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
512 }
513 }
514 } while (gim != null);
515 }
516
517 private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
518 {
519
456 UUID toAgentID = new UUID(im.toAgentID); 520 UUID toAgentID = new UUID(im.toAgentID);
521 PresenceInfo upd = null;
457 UUID regionID; 522 UUID regionID;
458 bool needToLookupAgent; 523 bool lookupAgent = false;
459 524
460 lock (m_UserRegionMap) 525 lock (m_UserRegionMap)
461 needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
462
463 while (true)
464 { 526 {
465 if (needToLookupAgent) 527 if (m_UserRegionMap.ContainsKey(toAgentID))
466 { 528 {
467 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); 529 upd = new PresenceInfo();
530 upd.RegionID = m_UserRegionMap[toAgentID];
468 531
469 UUID foundRegionID = UUID.Zero; 532 // We need to compare the current regionhandle with the previous region handle
470 533 // or the recursive loop will never end because it will never try to lookup the agent again
471 if (presences != null) 534 if (prevRegionID == upd.RegionID)
472 { 535 {
473 foreach (PresenceInfo p in presences) 536 lookupAgent = true;
474 {
475 if (p.RegionID != UUID.Zero)
476 {
477 foundRegionID = p.RegionID;
478 break;
479 }
480 }
481 } 537 }
482
483 // If not found or the found region is the same as the last lookup, then message is undeliverable
484 if (foundRegionID == UUID.Zero || foundRegionID == regionID)
485 break;
486 else
487 regionID = foundRegionID;
488 } 538 }
489 539 else
490 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
491 if (reginfo == null)
492 { 540 {
493 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); 541 lookupAgent = true;
494 break;
495 } 542 }
543 }
496 544
497 // Try to send the message to the agent via the retrieved region.
498 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
499 msgdata["region_handle"] = 0;
500 bool imresult = doIMSending(reginfo, msgdata);
501 545
502 // If the message delivery was successful, then cache the entry. 546 // Are we needing to look-up an agent?
503 if (imresult) 547 if (lookupAgent)
548 {
549 // Non-cached user agent lookup.
550 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
551 if (presences != null && presences.Length > 0)
504 { 552 {
505 lock (m_UserRegionMap) 553 foreach (PresenceInfo p in presences)
506 { 554 {
507 m_UserRegionMap[toAgentID] = regionID; 555 if (p.RegionID != UUID.Zero)
556 {
557 upd = p;
558 break;
559 }
508 } 560 }
509 result(true);
510 return;
511 } 561 }
512 562
513 // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried 563 if (upd != null)
514 // to use a locally cached region ID. All subsequent attempts need to lookup agent details from 564 {
515 // the presence service. 565 // check if we've tried this before..
516 needToLookupAgent = true; 566 // This is one way to end the recursive loop
567 //
568 if (upd.RegionID == prevRegionID)
569 {
570 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
571 HandleUndeliverableMessage(im, result);
572 return;
573 }
574 }
575 else
576 {
577 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
578 HandleUndeliverableMessage(im, result);
579 return;
580 }
517 } 581 }
518 582
519 // If we reached this point then the message was not deliverable. Remove the bad cache entry and 583 if (upd != null)
520 // signal the delivery failure. 584 {
521 lock (m_UserRegionMap) 585 GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
522 m_UserRegionMap.Remove(toAgentID); 586 upd.RegionID);
587 if (reginfo != null)
588 {
589 Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
590 // Not actually used anymore, left in for compatibility
591 // Remove at next interface change
592 //
593 msgdata["region_handle"] = 0;
594 bool imresult = doIMSending(reginfo, msgdata);
595 if (imresult)
596 {
597 // IM delivery successful, so store the Agent's location in our local cache.
598 lock (m_UserRegionMap)
599 {
600 if (m_UserRegionMap.ContainsKey(toAgentID))
601 {
602 m_UserRegionMap[toAgentID] = upd.RegionID;
603 }
604 else
605 {
606 m_UserRegionMap.Add(toAgentID, upd.RegionID);
607 }
608 }
609 result(true);
610 }
611 else
612 {
613 // try again, but lookup user this time.
614 // Warning, this must call the Async version
615 // of this method or we'll be making thousands of threads
616 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
617 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
523 618
524 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); 619 // This is recursive!!!!!
525 HandleUndeliverableMessage(im, result); 620 SendGridInstantMessageViaXMLRPCAsync(im, result,
621 upd.RegionID);
622 }
623 }
624 else
625 {
626 m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
627 HandleUndeliverableMessage(im, result);
628 }
629 }
630 else
631 {
632 HandleUndeliverableMessage(im, result);
633 }
526 } 634 }
527 635
528 /// <summary> 636 /// <summary>
@@ -622,8 +730,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
622 gim["position_z"] = msg.Position.Z.ToString(); 730 gim["position_z"] = msg.Position.Z.ToString();
623 gim["region_id"] = new UUID(msg.RegionID).ToString(); 731 gim["region_id"] = new UUID(msg.RegionID).ToString();
624 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)
734 gim["message_key"] = m_MessageKey;
625 return gim; 735 return gim;
626 } 736 }
627
628 } 737 }
629} 738}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 9cdb1c2..369d480 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -39,6 +39,13 @@ using OpenSim.Region.Framework.Scenes;
39 39
40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
41{ 41{
42 public struct SendReply
43 {
44 public bool Success;
45 public string Message;
46 public int Disposition;
47 }
48
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")]
43 public class OfflineMessageModule : ISharedRegionModule 50 public class OfflineMessageModule : ISharedRegionModule
44 { 51 {
@@ -49,6 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
49 private string m_RestURL = String.Empty; 56 private string m_RestURL = String.Empty;
50 IMessageTransferModule m_TransferModule = null; 57 IMessageTransferModule m_TransferModule = null;
51 private bool m_ForwardOfflineGroupMessages = true; 58 private bool m_ForwardOfflineGroupMessages = true;
59 private Dictionary<IClientAPI, List<UUID>> m_repliesSent= new Dictionary<IClientAPI, List<UUID>>();
52 60
53 public void Initialise(IConfigSource config) 61 public void Initialise(IConfigSource config)
54 { 62 {
@@ -168,11 +176,21 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
168 private void OnNewClient(IClientAPI client) 176 private void OnNewClient(IClientAPI client)
169 { 177 {
170 client.OnRetrieveInstantMessages += RetrieveInstantMessages; 178 client.OnRetrieveInstantMessages += RetrieveInstantMessages;
179 client.OnLogout += OnClientLoggedOut;
180 }
181
182 public void OnClientLoggedOut(IClientAPI client)
183 {
184 m_repliesSent.Remove(client);
171 } 185 }
172 186
173 private void RetrieveInstantMessages(IClientAPI client) 187 private void RetrieveInstantMessages(IClientAPI client)
174 { 188 {
175 if (m_RestURL != "") 189 if (m_RestURL == String.Empty)
190 {
191 return;
192 }
193 else
176 { 194 {
177 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId); 195 m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
178 196
@@ -180,28 +198,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
180 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>( 198 = SynchronousRestObjectRequester.MakeRequest<UUID, List<GridInstantMessage>>(
181 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); 199 "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
182 200
183 if (msglist == null) 201 if (msglist != null)
184 { 202 {
185 m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list."); 203 foreach (GridInstantMessage im in msglist)
186 return;
187 }
188
189 foreach (GridInstantMessage im in msglist)
190 {
191 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
192 // send it directly or else the item will be given twice
193 client.SendInstantMessage(im);
194 else
195 { 204 {
196 // Send through scene event manager so all modules get a chance 205 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
197 // to look at this message before it gets delivered. 206 // send it directly or else the item will be given twice
198 // 207 client.SendInstantMessage(im);
199 // Needed for proper state management for stored group 208 else
200 // invitations 209 {
201 // 210 // Send through scene event manager so all modules get a chance
202 Scene s = FindScene(client.AgentId); 211 // to look at this message before it gets delivered.
203 if (s != null) 212 //
204 s.EventManager.TriggerIncomingInstantMessage(im); 213 // Needed for proper state management for stored group
214 // invitations
215 //
216
217 im.offline = 1;
218
219 Scene s = FindScene(client.AgentId);
220 if (s != null)
221 s.EventManager.TriggerIncomingInstantMessage(im);
222 }
205 } 223 }
206 } 224 }
207 } 225 }
@@ -213,7 +231,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
213 im.dialog != (byte)InstantMessageDialog.MessageFromAgent && 231 im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
214 im.dialog != (byte)InstantMessageDialog.GroupNotice && 232 im.dialog != (byte)InstantMessageDialog.GroupNotice &&
215 im.dialog != (byte)InstantMessageDialog.GroupInvitation && 233 im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
216 im.dialog != (byte)InstantMessageDialog.InventoryOffered) 234 im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
235 im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
217 { 236 {
218 return; 237 return;
219 } 238 }
@@ -225,15 +244,60 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
225 return; 244 return;
226 } 245 }
227 246
247 Scene scene = FindScene(new UUID(im.fromAgentID));
248 if (scene == null)
249 scene = m_SceneList[0];
250
251// Avination new code
252// SendReply reply = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, SendReply>(
253// "POST", m_RestURL+"/SaveMessage/?scope=" +
254// scene.RegionInfo.ScopeID.ToString(), im);
255
256// current opensim and osgrid compatible
228 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>( 257 bool success = SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
229 "POST", m_RestURL+"/SaveMessage/", im, 10000); 258 "POST", m_RestURL+"/SaveMessage/", im, 10000);
259// current opensim and osgrid compatible end
230 260
231 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) 261 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
232 { 262 {
233 IClientAPI client = FindClient(new UUID(im.fromAgentID)); 263 IClientAPI client = FindClient(new UUID(im.fromAgentID));
234 if (client == null) 264 if (client == null)
235 return; 265 return;
266/* Avination new code
267 if (reply.Message == String.Empty)
268 reply.Message = "User is not logged in. " + (reply.Success ? "Message saved." : "Message not saved");
269
270 bool sendReply = true;
271
272 switch (reply.Disposition)
273 {
274 case 0: // Normal
275 break;
276 case 1: // Only once per user
277 if (m_repliesSent.ContainsKey(client) && m_repliesSent[client].Contains(new UUID(im.toAgentID)))
278 {
279 sendReply = false;
280 }
281 else
282 {
283 if (!m_repliesSent.ContainsKey(client))
284 m_repliesSent[client] = new List<UUID>();
285 m_repliesSent[client].Add(new UUID(im.toAgentID));
286 }
287 break;
288 }
236 289
290 if (sendReply)
291 {
292 client.SendInstantMessage(new GridInstantMessage(
293 null, new UUID(im.toAgentID),
294 "System", new UUID(im.fromAgentID),
295 (byte)InstantMessageDialog.MessageFromAgent,
296 reply.Message,
297 false, new Vector3()));
298 }
299*/
300// current opensim and osgrid compatible
237 client.SendInstantMessage(new GridInstantMessage( 301 client.SendInstantMessage(new GridInstantMessage(
238 null, new UUID(im.toAgentID), 302 null, new UUID(im.toAgentID),
239 "System", new UUID(im.fromAgentID), 303 "System", new UUID(im.fromAgentID),
@@ -241,6 +305,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
241 "User is not logged in. "+ 305 "User is not logged in. "+
242 (success ? "Message saved." : "Message not saved"), 306 (success ? "Message saved." : "Message not saved"),
243 false, new Vector3())); 307 false, new Vector3()));
308// current opensim and osgrid compatible end
244 } 309 }
245 } 310 }
246 } 311 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 8847414..8d11d20 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -565,6 +565,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
565 return null; 565 return null;
566 } 566 }
567 567
568 return account;
569 /*
568 try 570 try
569 { 571 {
570 string encpass = Util.Md5Hash(pass); 572 string encpass = Util.Md5Hash(pass);
@@ -585,6 +587,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
585 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e); 587 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
586 return null; 588 return null;
587 } 589 }
590 */
588 } 591 }
589 592
590 /// <summary> 593 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index bba48cc..085328c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -165,8 +165,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
165 if (im.binaryBucket.Length < 17) // Invalid 165 if (im.binaryBucket.Length < 17) // Invalid
166 return; 166 return;
167 167
168 UUID receipientID = new UUID(im.toAgentID); 168 UUID recipientID = new UUID(im.toAgentID);
169 ScenePresence user = scene.GetScenePresence(receipientID); 169 ScenePresence user = scene.GetScenePresence(recipientID);
170 UUID copyID; 170 UUID copyID;
171 171
172 // First byte is the asset type 172 // First byte is the asset type
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
181 folderID, new UUID(im.toAgentID)); 181 folderID, new UUID(im.toAgentID));
182 182
183 InventoryFolderBase folderCopy 183 InventoryFolderBase folderCopy
184 = scene.GiveInventoryFolder(client, receipientID, client.AgentId, folderID, UUID.Zero); 184 = scene.GiveInventoryFolder(client, recipientID, client.AgentId, folderID, UUID.Zero);
185 185
186 if (folderCopy == null) 186 if (folderCopy == null)
187 { 187 {
@@ -239,6 +239,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
239 im.imSessionID = copyID.Guid; 239 im.imSessionID = copyID.Guid;
240 } 240 }
241 241
242 im.offline = 0;
243
242 // Send the IM to the recipient. The item is already 244 // Send the IM to the recipient. The item is already
243 // in their inventory, so it will not be lost if 245 // in their inventory, so it will not be lost if
244 // they are offline. 246 // they are offline.
@@ -258,8 +260,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
258 }); 260 });
259 } 261 }
260 } 262 }
261 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) 263 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
264 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
262 { 265 {
266 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
267 IInventoryService invService = scene.InventoryService;
268
269 // Special case: folder redirect.
270 // RLV uses this
271 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
272 {
273 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, client.AgentId);
274 folder = invService.GetFolder(folder);
275
276 if (folder != null)
277 {
278 if (im.binaryBucket.Length >= 16)
279 {
280 UUID destFolderID = new UUID(im.binaryBucket, 0);
281 if (destFolderID != UUID.Zero)
282 {
283 InventoryFolderBase destFolder = new InventoryFolderBase(destFolderID, client.AgentId);
284 destFolder = invService.GetFolder(destFolder);
285 if (destFolder != null)
286 {
287 if (folder.ParentID != destFolder.ID)
288 {
289 folder.ParentID = destFolder.ID;
290 invService.MoveFolder(folder);
291 client.SendBulkUpdateInventory(folder);
292 }
293 }
294 }
295 }
296 }
297 }
298
263 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 299 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
264 300
265 if (user != null) // Local 301 if (user != null) // Local
@@ -269,27 +305,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
269 else 305 else
270 { 306 {
271 if (m_TransferModule != null) 307 if (m_TransferModule != null)
272 m_TransferModule.SendInstantMessage(im, delegate(bool success) { 308 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
273
274 // justincc - FIXME: Comment out for now. This code was added in commit db91044 Mon Aug 22 2011
275 // and is apparently supposed to fix bulk inventory updates after accepting items. But
276 // instead it appears to cause two copies of an accepted folder for the receiving user in
277 // at least some cases. Folder/item update is already done when the offer is made (see code above)
278
279// // Send BulkUpdateInventory
280// IInventoryService invService = scene.InventoryService;
281// UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item /folder, back from it's trip
282//
283// InventoryFolderBase folder = new InventoryFolderBase(inventoryEntityID, client.AgentId);
284// folder = invService.GetFolder(folder);
285//
286// ScenePresence fromUser = scene.GetScenePresence(new UUID(im.fromAgentID));
287//
288// // If the user has left the scene by the time the message comes back then we can't send
289// // them the update.
290// if (fromUser != null)
291// fromUser.ControllingClient.SendBulkUpdateInventory(folder);
292 });
293 } 309 }
294 } 310 }
295 311
@@ -402,6 +418,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
402 previousParentFolderID = folder.ParentID; 418 previousParentFolderID = folder.ParentID;
403 folder.ParentID = trashFolder.ID; 419 folder.ParentID = trashFolder.ID;
404 invService.MoveFolder(folder); 420 invService.MoveFolder(folder);
421 client.SendBulkUpdateInventory(folder);
405 } 422 }
406 } 423 }
407 424
@@ -453,18 +470,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
453 /// <param name="im"></param> 470 /// <param name="im"></param>
454 private void OnGridInstantMessage(GridInstantMessage im) 471 private void OnGridInstantMessage(GridInstantMessage im)
455 { 472 {
456 // Check if it's a type of message that we should handle
457 if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
458 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
459 || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
460 || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
461 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
462 return;
463
464 m_log.DebugFormat(
465 "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
466 (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
467
468 // Check if this is ours to handle 473 // Check if this is ours to handle
469 // 474 //
470 Scene scene = FindClientScene(new UUID(im.toAgentID)); 475 Scene scene = FindClientScene(new UUID(im.toAgentID));
@@ -475,32 +480,100 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
475 // Find agent to deliver to 480 // Find agent to deliver to
476 // 481 //
477 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 482 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
483 if (user == null)
484 return;
478 485
479 if (user != null) 486 // This requires a little bit of processing because we have to make the
487 // new item visible in the recipient's inventory here
488 //
489 if (im.dialog == (byte) InstantMessageDialog.InventoryOffered)
480 { 490 {
481 user.ControllingClient.SendInstantMessage(im); 491 if (im.binaryBucket.Length < 17) // Invalid
492 return;
493
494 UUID recipientID = new UUID(im.toAgentID);
482 495
483 if (im.dialog == (byte)InstantMessageDialog.InventoryOffered) 496 // First byte is the asset type
484 { 497 AssetType assetType = (AssetType)im.binaryBucket[0];
485 AssetType assetType = (AssetType)im.binaryBucket[0];
486 UUID inventoryID = new UUID(im.binaryBucket, 1);
487 498
488 IInventoryService invService = scene.InventoryService; 499 if (AssetType.Folder == assetType)
489 InventoryNodeBase node = null; 500 {
490 if (AssetType.Folder == assetType) 501 UUID folderID = new UUID(im.binaryBucket, 1);
502
503 InventoryFolderBase given =
504 new InventoryFolderBase(folderID, recipientID);
505 InventoryFolderBase folder =
506 scene.InventoryService.GetFolder(given);
507
508 if (folder != null)
509 user.ControllingClient.SendBulkUpdateInventory(folder);
510 }
511 else
512 {
513 UUID itemID = new UUID(im.binaryBucket, 1);
514
515 InventoryItemBase given =
516 new InventoryItemBase(itemID, recipientID);
517 InventoryItemBase item =
518 scene.InventoryService.GetItem(given);
519
520 if (item != null)
491 { 521 {
492 InventoryFolderBase folder = new InventoryFolderBase(inventoryID, new UUID(im.toAgentID)); 522 user.ControllingClient.SendBulkUpdateInventory(item);
493 node = invService.GetFolder(folder);
494 } 523 }
495 else 524 }
525 user.ControllingClient.SendInstantMessage(im);
526 }
527 if (im.dialog == (byte) InstantMessageDialog.TaskInventoryOffered)
528 {
529 if (im.binaryBucket.Length < 1) // Invalid
530 return;
531
532 UUID recipientID = new UUID(im.toAgentID);
533
534 // Bucket is the asset type
535 AssetType assetType = (AssetType)im.binaryBucket[0];
536
537 if (AssetType.Folder == assetType)
538 {
539 UUID folderID = new UUID(im.imSessionID);
540
541 InventoryFolderBase given =
542 new InventoryFolderBase(folderID, recipientID);
543 InventoryFolderBase folder =
544 scene.InventoryService.GetFolder(given);
545
546 if (folder != null)
547 user.ControllingClient.SendBulkUpdateInventory(folder);
548 }
549 else
550 {
551 UUID itemID = new UUID(im.imSessionID);
552
553 InventoryItemBase given =
554 new InventoryItemBase(itemID, recipientID);
555 InventoryItemBase item =
556 scene.InventoryService.GetItem(given);
557
558 if (item != null)
496 { 559 {
497 InventoryItemBase item = new InventoryItemBase(inventoryID, new UUID(im.toAgentID)); 560 user.ControllingClient.SendBulkUpdateInventory(item);
498 node = invService.GetItem(item);
499 } 561 }
500
501 if (node != null)
502 user.ControllingClient.SendBulkUpdateInventory(node);
503 } 562 }
563
564 // Fix up binary bucket since this may be 17 chars long here
565 Byte[] bucket = new Byte[1];
566 bucket[0] = im.binaryBucket[0];
567 im.binaryBucket = bucket;
568
569 user.ControllingClient.SendInstantMessage(im);
570 }
571 else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted ||
572 im.dialog == (byte) InstantMessageDialog.InventoryDeclined ||
573 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined ||
574 im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
575 {
576 user.ControllingClient.SendInstantMessage(im);
504 } 577 }
505 } 578 }
506 } 579 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 465ffbc..c517a30 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -163,16 +163,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
163 scene.RegionInfo.RegionHandle, 163 scene.RegionInfo.RegionHandle,
164 (uint)presence.AbsolutePosition.X, 164 (uint)presence.AbsolutePosition.X,
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)Math.Ceiling(presence.AbsolutePosition.Z)); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("[LURE MODULE]: 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 = new GridInstantMessage(scene, client.AgentId, 170 GridInstantMessage m;
171 client.FirstName+" "+client.LastName, targetid, 171
172 (byte)InstantMessageDialog.RequestTeleport, false, 172 if (scene.Permissions.IsAdministrator(client.AgentId) && presence.GodLevel >= 200 && (!scene.Permissions.IsAdministrator(targetid)))
173 message, dest, false, presence.AbsolutePosition, 173 {
174 new Byte[0], true); 174 m = new GridInstantMessage(scene, client.AgentId,
175 175 client.FirstName+" "+client.LastName, targetid,
176 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
177 message, dest, false, presence.AbsolutePosition,
178 new Byte[0], true);
179 }
180 else
181 {
182 m = new GridInstantMessage(scene, client.AgentId,
183 client.FirstName+" "+client.LastName, targetid,
184 (byte)InstantMessageDialog.RequestTeleport, false,
185 message, dest, false, presence.AbsolutePosition,
186 new Byte[0], true);
187 }
188
176 if (m_TransferModule != null) 189 if (m_TransferModule != null)
177 { 190 {
178 m_TransferModule.SendInstantMessage(m, 191 m_TransferModule.SendInstantMessage(m,
@@ -207,7 +220,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
207 { 220 {
208 // Forward remote teleport requests 221 // Forward remote teleport requests
209 // 222 //
210 if (msg.dialog != 22) 223 if (msg.dialog != (byte)InstantMessageDialog.RequestTeleport &&
224 msg.dialog != (byte)InstantMessageDialog.GodLikeRequestTeleport)
211 return; 225 return;
212 226
213 if (m_TransferModule != null) 227 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index c20369c..145f3db 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -873,6 +873,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
873 } 873 }
874 #endregion Notes 874 #endregion Notes
875 875
876
876 #region User Preferences 877 #region User Preferences
877 /// <summary> 878 /// <summary>
878 /// Updates the user preferences. 879 /// Updates the user preferences.
@@ -1402,5 +1403,182 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
1402 return null; 1403 return null;
1403 } 1404 }
1404 #endregion Util 1405 #endregion Util
1406
1407 #region Web Util
1408 /// <summary>
1409 /// Sends json-rpc request with a serializable type.
1410 /// </summary>
1411 /// <returns>
1412 /// OSD Map.
1413 /// </returns>
1414 /// <param name='parameters'>
1415 /// Serializable type .
1416 /// </param>
1417 /// <param name='method'>
1418 /// Json-rpc method to call.
1419 /// </param>
1420 /// <param name='uri'>
1421 /// URI of json-rpc service.
1422 /// </param>
1423 /// <param name='jsonId'>
1424 /// Id for our call.
1425 /// </param>
1426 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1427 {
1428 if (jsonId == null)
1429 throw new ArgumentNullException ("jsonId");
1430 if (uri == null)
1431 throw new ArgumentNullException ("uri");
1432 if (method == null)
1433 throw new ArgumentNullException ("method");
1434 if (parameters == null)
1435 throw new ArgumentNullException ("parameters");
1436
1437 // Prep our payload
1438 OSDMap json = new OSDMap();
1439
1440 json.Add("jsonrpc", OSD.FromString("2.0"));
1441 json.Add("id", OSD.FromString(jsonId));
1442 json.Add("method", OSD.FromString(method));
1443
1444 json.Add("params", OSD.SerializeMembers(parameters));
1445
1446 string jsonRequestData = OSDParser.SerializeJsonString(json);
1447 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1448
1449 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1450
1451 webRequest.ContentType = "application/json-rpc";
1452 webRequest.Method = "POST";
1453
1454 Stream dataStream = webRequest.GetRequestStream();
1455 dataStream.Write(content, 0, content.Length);
1456 dataStream.Close();
1457
1458 WebResponse webResponse = null;
1459 try
1460 {
1461 webResponse = webRequest.GetResponse();
1462 }
1463 catch (WebException e)
1464 {
1465 Console.WriteLine("Web Error" + e.Message);
1466 Console.WriteLine ("Please check input");
1467 return false;
1468 }
1469
1470 OSDMap mret = new OSDMap();
1471
1472 using (Stream rstream = webResponse.GetResponseStream())
1473 {
1474 try
1475 {
1476 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1477 }
1478 catch (Exception e)
1479 {
1480 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1481 if (webResponse != null)
1482 webResponse.Close();
1483 return false;
1484 }
1485 }
1486
1487 if (webResponse != null)
1488 webResponse.Close();
1489
1490 if (mret.ContainsKey("error"))
1491 return false;
1492
1493 // get params...
1494 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1495 return true;
1496 }
1497
1498 /// <summary>
1499 /// Sends json-rpc request with OSD parameter.
1500 /// </summary>
1501 /// <returns>
1502 /// The rpc request.
1503 /// </returns>
1504 /// <param name='data'>
1505 /// data - incoming as parameters, outgong as result/error
1506 /// </param>
1507 /// <param name='method'>
1508 /// Json-rpc method to call.
1509 /// </param>
1510 /// <param name='uri'>
1511 /// URI of json-rpc service.
1512 /// </param>
1513 /// <param name='jsonId'>
1514 /// If set to <c>true</c> json identifier.
1515 /// </param>
1516 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1517 {
1518 OSDMap map = new OSDMap();
1519
1520 map["jsonrpc"] = "2.0";
1521 if(string.IsNullOrEmpty(jsonId))
1522 map["id"] = UUID.Random().ToString();
1523 else
1524 map["id"] = jsonId;
1525
1526 map["method"] = method;
1527 map["params"] = data;
1528
1529 string jsonRequestData = OSDParser.SerializeJsonString(map);
1530 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1531
1532 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1533 webRequest.ContentType = "application/json-rpc";
1534 webRequest.Method = "POST";
1535
1536 Stream dataStream = webRequest.GetRequestStream();
1537 dataStream.Write(content, 0, content.Length);
1538 dataStream.Close();
1539
1540 WebResponse webResponse = null;
1541 try
1542 {
1543 webResponse = webRequest.GetResponse();
1544 }
1545 catch (WebException e)
1546 {
1547 Console.WriteLine("Web Error" + e.Message);
1548 Console.WriteLine ("Please check input");
1549 return false;
1550 }
1551
1552 OSDMap response = new OSDMap();
1553
1554 using (Stream rstream = webResponse.GetResponseStream())
1555 {
1556 try
1557 {
1558 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1559 }
1560 catch (Exception e)
1561 {
1562 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1563 if (webResponse != null)
1564 webResponse.Close();
1565 return false;
1566 }
1567 }
1568
1569 if (webResponse != null)
1570 webResponse.Close();
1571
1572 if(response.ContainsKey("error"))
1573 {
1574 data = response["error"];
1575 return false;
1576 }
1577
1578 data = response;
1579
1580 return true;
1581 }
1582 #endregion Web Util
1405 } 1583 }
1406} 1584}
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 817ef85..44eee89 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Framework
57 /// <summary> 57 /// <summary>
58 /// Each agent has its own capabilities handler. 58 /// Each agent has its own capabilities handler.
59 /// </summary> 59 /// </summary>
60 protected Dictionary<UUID, Caps> m_capsObjects = new Dictionary<UUID, Caps>(); 60 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>();
61 61
62 protected Dictionary<UUID, string> m_capsPaths = new Dictionary<UUID, string>(); 62 protected Dictionary<UUID, string> m_capsPaths = new Dictionary<UUID, string>();
63 63
@@ -118,23 +118,46 @@ namespace OpenSim.Region.CoreModules.Framework
118 get { return null; } 118 get { return null; }
119 } 119 }
120 120
121 public void CreateCaps(UUID agentId) 121 public void CreateCaps(UUID agentId, uint circuitCode)
122 { 122 {
123 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId)) 123 int ts = Util.EnvironmentTickCount();
124 return; 124/* this as no business here...
125 * must be done elsewhere ( and is )
126 int flags = m_scene.GetUserFlags(agentId);
127
128 m_log.ErrorFormat("[CreateCaps]: banCheck {0} ", Util.EnvironmentTickCountSubtract(ts));
125 129
130 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
131 return;
132*/
126 Caps caps; 133 Caps caps;
127 String capsObjectPath = GetCapsPath(agentId); 134 String capsObjectPath = GetCapsPath(agentId);
128 135
129 lock (m_capsObjects) 136 lock (m_capsObjects)
130 { 137 {
131 if (m_capsObjects.ContainsKey(agentId)) 138 if (m_capsObjects.ContainsKey(circuitCode))
132 { 139 {
133 Caps oldCaps = m_capsObjects[agentId]; 140 Caps oldCaps = m_capsObjects[circuitCode];
134 141
135 //m_log.WarnFormat( 142
136 // "[CAPS]: Recreating caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ", 143 if (capsObjectPath == oldCaps.CapsObjectPath)
137 // agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath); 144 {
145 m_log.WarnFormat(
146 "[CAPS]: Reusing caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ",
147 agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath);
148 return;
149 }
150 else
151 {
152 // not reusing add extra melanie cleanup
153 // Remove tge handlers. They may conflict with the
154 // new object created below
155 oldCaps.DeregisterHandlers();
156
157 // Better safe ... should not be needed but also
158 // no big deal
159 m_capsObjects.Remove(circuitCode);
160 }
138 } 161 }
139 162
140// m_log.DebugFormat( 163// m_log.DebugFormat(
@@ -145,13 +168,17 @@ namespace OpenSim.Region.CoreModules.Framework
145 (MainServer.Instance == null) ? 0: MainServer.Instance.Port, 168 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
146 capsObjectPath, agentId, m_scene.RegionInfo.RegionName); 169 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
147 170
148 m_capsObjects[agentId] = caps; 171 m_log.ErrorFormat("[CreateCaps]: new caps agent {0}, circuit {1}, path {2}, time {3} ",agentId,
149 } 172 circuitCode,caps.CapsObjectPath, Util.EnvironmentTickCountSubtract(ts));
150 173
174 m_capsObjects[circuitCode] = caps;
175 }
151 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); 176 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps);
177// m_log.ErrorFormat("[CreateCaps]: end {0} ", Util.EnvironmentTickCountSubtract(ts));
178
152 } 179 }
153 180
154 public void RemoveCaps(UUID agentId) 181 public void RemoveCaps(UUID agentId, uint circuitCode)
155 { 182 {
156 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName); 183 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName);
157 lock (m_childrenSeeds) 184 lock (m_childrenSeeds)
@@ -164,14 +191,24 @@ namespace OpenSim.Region.CoreModules.Framework
164 191
165 lock (m_capsObjects) 192 lock (m_capsObjects)
166 { 193 {
167 if (m_capsObjects.ContainsKey(agentId)) 194 if (m_capsObjects.ContainsKey(circuitCode))
168 { 195 {
169 m_capsObjects[agentId].DeregisterHandlers(); 196 m_capsObjects[circuitCode].DeregisterHandlers();
170 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]); 197 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[circuitCode]);
171 m_capsObjects.Remove(agentId); 198 m_capsObjects.Remove(circuitCode);
172 } 199 }
173 else 200 else
174 { 201 {
202 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
203 {
204 if (kvp.Value.AgentID == agentId)
205 {
206 kvp.Value.DeregisterHandlers();
207 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, kvp.Value);
208 m_capsObjects.Remove(kvp.Key);
209 return;
210 }
211 }
175 m_log.WarnFormat( 212 m_log.WarnFormat(
176 "[CAPS]: Received request to remove CAPS handler for root agent {0} in {1}, but no such CAPS handler found!", 213 "[CAPS]: Received request to remove CAPS handler for root agent {0} in {1}, but no such CAPS handler found!",
177 agentId, m_scene.RegionInfo.RegionName); 214 agentId, m_scene.RegionInfo.RegionName);
@@ -179,19 +216,30 @@ namespace OpenSim.Region.CoreModules.Framework
179 } 216 }
180 } 217 }
181 218
182 public Caps GetCapsForUser(UUID agentId) 219 public Caps GetCapsForUser(uint circuitCode)
183 { 220 {
184 lock (m_capsObjects) 221 lock (m_capsObjects)
185 { 222 {
186 if (m_capsObjects.ContainsKey(agentId)) 223 if (m_capsObjects.ContainsKey(circuitCode))
187 { 224 {
188 return m_capsObjects[agentId]; 225 return m_capsObjects[circuitCode];
189 } 226 }
190 } 227 }
191 228
192 return null; 229 return null;
193 } 230 }
194 231
232 public void ActivateCaps(uint circuitCode)
233 {
234 lock (m_capsObjects)
235 {
236 if (m_capsObjects.ContainsKey(circuitCode))
237 {
238 m_capsObjects[circuitCode].Activate();
239 }
240 }
241 }
242
195 public void SetAgentCapsSeeds(AgentCircuitData agent) 243 public void SetAgentCapsSeeds(AgentCircuitData agent)
196 { 244 {
197 lock (m_capsPaths) 245 lock (m_capsPaths)
@@ -289,9 +337,9 @@ namespace OpenSim.Region.CoreModules.Framework
289 337
290 lock (m_capsObjects) 338 lock (m_capsObjects)
291 { 339 {
292 foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) 340 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
293 { 341 {
294 capsReport.AppendFormat("** User {0}:\n", kvp.Key); 342 capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
295 Caps caps = kvp.Value; 343 Caps caps = kvp.Value;
296 344
297 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) 345 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
@@ -339,6 +387,7 @@ namespace OpenSim.Region.CoreModules.Framework
339 387
340 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName) 388 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName)
341 { 389 {
390 /*
342 sb.AppendFormat("Capability name {0}\n", capName); 391 sb.AppendFormat("Capability name {0}\n", capName);
343 392
344 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 393 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
@@ -384,10 +433,12 @@ namespace OpenSim.Region.CoreModules.Framework
384 } 433 }
385 434
386 sb.Append(cdt.ToString()); 435 sb.Append(cdt.ToString());
436 */
387 } 437 }
388 438
389 private void BuildSummaryStatsByCapReport(StringBuilder sb) 439 private void BuildSummaryStatsByCapReport(StringBuilder sb)
390 { 440 {
441 /*
391 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 442 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
392 cdt.AddColumn("Name", 34); 443 cdt.AddColumn("Name", 34);
393 cdt.AddColumn("Req Received", 12); 444 cdt.AddColumn("Req Received", 12);
@@ -444,10 +495,12 @@ namespace OpenSim.Region.CoreModules.Framework
444 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]); 495 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
445 496
446 sb.Append(cdt.ToString()); 497 sb.Append(cdt.ToString());
498 */
447 } 499 }
448 500
449 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams) 501 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams)
450 { 502 {
503 /*
451 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) 504 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
452 return; 505 return;
453 506
@@ -478,10 +531,12 @@ namespace OpenSim.Region.CoreModules.Framework
478 } 531 }
479 532
480 MainConsole.Instance.Output(sb.ToString()); 533 MainConsole.Instance.Output(sb.ToString());
534 */
481 } 535 }
482 536
483 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp) 537 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp)
484 { 538 {
539 /*
485 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root"); 540 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root");
486 541
487 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 542 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
@@ -507,10 +562,12 @@ namespace OpenSim.Region.CoreModules.Framework
507 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled); 562 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
508 563
509 sb.Append(cdt.ToString()); 564 sb.Append(cdt.ToString());
565 */
510 } 566 }
511 567
512 private void BuildSummaryStatsByUserReport(StringBuilder sb) 568 private void BuildSummaryStatsByUserReport(StringBuilder sb)
513 { 569 {
570 /*
514 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 571 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
515 cdt.AddColumn("Name", 32); 572 cdt.AddColumn("Name", 32);
516 cdt.AddColumn("Type", 5); 573 cdt.AddColumn("Type", 5);
@@ -550,6 +607,7 @@ namespace OpenSim.Region.CoreModules.Framework
550 ); 607 );
551 608
552 sb.Append(cdt.ToString()); 609 sb.Append(cdt.ToString());
610 */
553 } 611 }
554 612
555 private class CapTableRow 613 private class CapTableRow
@@ -566,4 +624,4 @@ namespace OpenSim.Region.CoreModules.Framework
566 } 624 }
567 } 625 }
568 } 626 }
569} \ No newline at end of file 627}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index e4bc113..ed93f05 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -147,13 +147,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
147 // Add this agent in this region as a banned person 147 // Add this agent in this region as a banned person
148 public void Add(ulong pRegionHandle, UUID pAgentID) 148 public void Add(ulong pRegionHandle, UUID pAgentID)
149 { 149 {
150 this.Add(pRegionHandle, pAgentID, 45, 15);
151 }
152
153 public void Add(ulong pRegionHandle, UUID pAgentID, double newTime, double extendTime)
154 {
150 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache)) 155 if (!m_bannedRegions.TryGetValue(pAgentID, out m_idCache))
151 { 156 {
152 m_idCache = new ExpiringCache<ulong, DateTime>(); 157 m_idCache = new ExpiringCache<ulong, DateTime>();
153 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(45)); 158 m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(newTime));
154 } 159 }
155 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); 160 m_idCache.Add(pRegionHandle, DateTime.Now + TimeSpan.FromSeconds(extendTime), TimeSpan.FromSeconds(extendTime));
156 } 161 }
162
157 // Remove the agent from the region's banned list 163 // Remove the agent from the region's banned list
158 public void Remove(ulong pRegionHandle, UUID pAgentID) 164 public void Remove(ulong pRegionHandle, UUID pAgentID)
159 { 165 {
@@ -163,6 +169,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
163 } 169 }
164 } 170 }
165 } 171 }
172
166 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache(); 173 private BannedRegionCache m_bannedRegionCache = new BannedRegionCache();
167 174
168 private IEventQueue m_eqModule; 175 private IEventQueue m_eqModule;
@@ -451,16 +458,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
451 } 458 }
452 459
453 // TODO: Get proper AVG Height 460 // TODO: Get proper AVG Height
454 float localAVHeight = 1.56f; 461 float localHalfAVHeight = 0.8f;
462 if (sp.Appearance != null)
463 localHalfAVHeight = sp.Appearance.AvatarHeight / 2;
464
455 float posZLimit = 22; 465 float posZLimit = 22;
456 466
457 // TODO: Check other Scene HeightField 467 // TODO: Check other Scene HeightField
458 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y]; 468 posZLimit = (float)sp.Scene.Heightmap[(int)position.X, (int)position.Y];
459 469
460 float newPosZ = posZLimit + localAVHeight; 470 posZLimit += localHalfAVHeight + 0.1f;
461 if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 471
472 if ((position.Z < posZLimit) && !(Single.IsInfinity(posZLimit) || Single.IsNaN(posZLimit)))
462 { 473 {
463 position.Z = newPosZ; 474 position.Z = posZLimit;
464 } 475 }
465 476
466 if (sp.Flying) 477 if (sp.Flying)
@@ -559,9 +570,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
559 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY); 570 Util.RegionHandleToRegionLoc(regionHandle, out regX, out regY);
560 571
561 MapBlockData block = new MapBlockData(); 572 MapBlockData block = new MapBlockData();
562 block.X = (ushort)regX; 573 block.X = (ushort)(regX);
563 block.Y = (ushort)regY; 574 block.Y = (ushort)(regY);
564 block.Access = (byte)SimAccess.Down; 575 block.Access = (byte)SimAccess.Down; // == not there
565 576
566 List<MapBlockData> blocks = new List<MapBlockData>(); 577 List<MapBlockData> blocks = new List<MapBlockData>();
567 blocks.Add(block); 578 blocks.Add(block);
@@ -696,10 +707,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
696 return; 707 return;
697 } 708 }
698 709
699 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
700 Util.RegionHandleToRegionLoc(reg.RegionHandle, out newRegionX, out newRegionY);
701 Util.RegionHandleToRegionLoc(sp.Scene.RegionInfo.RegionHandle, out oldRegionX, out oldRegionY);
702
703 ulong destinationHandle = finalDestination.RegionHandle; 710 ulong destinationHandle = finalDestination.RegionHandle;
704 711
705 // Let's do DNS resolution only once in this process, please! 712 // Let's do DNS resolution only once in this process, please!
@@ -768,7 +775,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
768 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); 775 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
769 agentCircuit.startpos = position; 776 agentCircuit.startpos = position;
770 agentCircuit.child = true; 777 agentCircuit.child = true;
771 agentCircuit.Appearance = sp.Appearance; 778
779// agentCircuit.Appearance = sp.Appearance;
780// agentCircuit.Appearance = new AvatarAppearance(sp.Appearance, true, false);
781 agentCircuit.Appearance = new AvatarAppearance();
782 agentCircuit.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
783
772 if (currentAgentCircuit != null) 784 if (currentAgentCircuit != null)
773 { 785 {
774 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; 786 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -779,24 +791,51 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
779 agentCircuit.Id0 = currentAgentCircuit.Id0; 791 agentCircuit.Id0 = currentAgentCircuit.Id0;
780 } 792 }
781 793
782 // if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 794 IClientIPEndpoint ipepClient;
783 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance, 795
784 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY)); 796 uint newRegionX, newRegionY, oldRegionX, oldRegionY;
785 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY)) 797 Util.RegionHandleToRegionLoc(destinationHandle, out newRegionX, out newRegionY);
798 Util.RegionHandleToRegionLoc(sourceRegion.RegionHandle, out oldRegionX, out oldRegionY);
799 int oldSizeX = (int)sourceRegion.RegionSizeX;
800 int oldSizeY = (int)sourceRegion.RegionSizeY;
801 int newSizeX = finalDestination.RegionSizeX;
802 int newSizeY = finalDestination.RegionSizeY;
803
804 bool OutSideViewRange = NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY,
805 oldSizeX, oldSizeY, newSizeX, newSizeY);
806
807 if (OutSideViewRange)
786 { 808 {
787 // brand new agent, let's create a new caps seed 809 m_log.DebugFormat(
810 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
811 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
812
813 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
814 #region IP Translation for NAT
815 // Uses ipepClient above
816 if (sp.ClientView.TryGet(out ipepClient))
817 {
818 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
819 }
820 #endregion
788 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 821 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
789 } 822 }
823 else
824 {
825 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
826 if (agentCircuit.CapsPath == null)
827 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
828 }
790 829
791 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 830 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2
792 if (ctx.OutboundVersion >= 0.2f) 831 if (ctx.OutboundVersion >= 0.2f)
793 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, ctx, out reason); 832 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange , ctx, out reason);
794 else 833 else
795 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, ctx, out reason); 834 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, OutSideViewRange, ctx, out reason);
796 } 835 }
797 836
798 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, 837 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
799 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, EntityTransferContext ctx, out string reason) 838 IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason)
800 { 839 {
801 ulong destinationHandle = finalDestination.RegionHandle; 840 ulong destinationHandle = finalDestination.RegionHandle;
802 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 841 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
@@ -805,10 +844,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
805 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}", 844 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
806 sp.Name, Scene.Name, finalDestination.RegionName); 845 sp.Name, Scene.Name, finalDestination.RegionName);
807 846
847 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
848
808 // Let's create an agent there if one doesn't exist yet. 849 // Let's create an agent there if one doesn't exist yet.
809 // NOTE: logout will always be false for a non-HG teleport. 850 // NOTE: logout will always be false for a non-HG teleport.
810 bool logout = false; 851 bool logout = false;
811 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 852 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
812 { 853 {
813 m_interRegionTeleportFailures.Value++; 854 m_interRegionTeleportFailures.Value++;
814 855
@@ -846,28 +887,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
846 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 887 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
847 888
848 // OK, it got this agent. Let's close some child agents 889 // OK, it got this agent. Let's close some child agents
849 sp.CloseChildAgents(newRegionX, newRegionY);
850 890
851 IClientIPEndpoint ipepClient; 891 if (OutSideViewRange)
852 string capsPath = String.Empty;
853 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
854 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
855 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
856 { 892 {
857 m_log.DebugFormat(
858 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
859 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
860
861 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
862 #region IP Translation for NAT
863 // Uses ipepClient above
864 if (sp.ClientView.TryGet(out ipepClient))
865 {
866 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
867 }
868 #endregion
869 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
870
871 if (m_eqModule != null) 893 if (m_eqModule != null)
872 { 894 {
873 // The EnableSimulator message makes the client establish a connection with the destination 895 // The EnableSimulator message makes the client establish a connection with the destination
@@ -897,15 +919,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
897 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint); 919 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
898 } 920 }
899 } 921 }
900 else
901 {
902 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
903 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
904 }
905 922
906 // Let's send a full update of the agent. This is a synchronous call. 923 // Let's send a full update of the agent. This is a synchronous call.
907 AgentData agent = new AgentData(); 924 AgentData agent = new AgentData();
908 sp.CopyTo(agent); 925 sp.CopyTo(agent);
926
927 if ((teleportFlags & (uint)TeleportFlags.IsFlying) != 0)
928 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
929
909 agent.Position = agentCircuit.startpos; 930 agent.Position = agentCircuit.startpos;
910 SetCallbackURL(agent, sp.Scene.RegionInfo); 931 SetCallbackURL(agent, sp.Scene.RegionInfo);
911 932
@@ -927,7 +948,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
927 // destination region but the viewer cannot establish the connection (e.g. due to network issues between 948 // destination region but the viewer cannot establish the connection (e.g. due to network issues between
928 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then 949 // the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
929 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail(). 950 // there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail().
930 if (!UpdateAgent(reg, finalDestination, agent, sp)) 951 if (!UpdateAgent(reg, finalDestination, agent, sp, ctx))
931 { 952 {
932 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 953 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
933 { 954 {
@@ -1007,7 +1028,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1007 return; 1028 return;
1008 } 1029 }
1009 1030
1010 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1011 1031
1012/* 1032/*
1013 // TODO: This may be 0.6. Check if still needed 1033 // TODO: This may be 0.6. Check if still needed
@@ -1020,18 +1040,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1020 } 1040 }
1021*/ 1041*/
1022 1042
1023 // May need to logout or other cleanup 1043 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1024 AgentHasMovedAway(sp, logout);
1025 1044
1026 // Well, this is it. The agent is over there. 1045 sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1027 KillEntity(sp.Scene, sp.LocalId);
1028 1046
1029 // Now let's make it officially a child agent 1047 // call HG hook
1030 sp.MakeChildAgent(); 1048 AgentHasMovedAway(sp, logout);
1049
1050 sp.HasMovedAway(!(OutSideViewRange || logout));
1051
1052 // Now let's make it officially a child agent
1053 sp.MakeChildAgent(destinationHandle);
1031 1054
1032 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1055 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1033 1056
1034 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1057 if (NeedsClosing(reg, OutSideViewRange))
1035 { 1058 {
1036 if (!sp.Scene.IncomingPreCloseClient(sp)) 1059 if (!sp.Scene.IncomingPreCloseClient(sp))
1037 return; 1060 return;
@@ -1043,26 +1066,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1043 // This sleep can be increased if necessary. However, whilst it's active, 1066 // This sleep can be increased if necessary. However, whilst it's active,
1044 // an agent cannot teleport back to this region if it has teleported away. 1067 // an agent cannot teleport back to this region if it has teleported away.
1045 Thread.Sleep(2000); 1068 Thread.Sleep(2000);
1046 1069 if (m_eqModule != null && !sp.DoNotCloseAfterTeleport)
1070 m_eqModule.DisableSimulator(sp.RegionHandle,sp.UUID);
1071 Thread.Sleep(500);
1047 sp.Scene.CloseAgent(sp.UUID, false); 1072 sp.Scene.CloseAgent(sp.UUID, false);
1048 } 1073 }
1049 else
1050 {
1051 // now we have a child agent in this region.
1052 sp.Reset();
1053 }
1054 } 1074 }
1055 1075
1056 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination, 1076 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
1057 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, EntityTransferContext ctx, out string reason) 1077 IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason)
1058 { 1078 {
1059 ulong destinationHandle = finalDestination.RegionHandle; 1079 ulong destinationHandle = finalDestination.RegionHandle;
1060 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 1080 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1061 1081
1082 string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);;
1083
1062 // Let's create an agent there if one doesn't exist yet. 1084 // Let's create an agent there if one doesn't exist yet.
1063 // NOTE: logout will always be false for a non-HG teleport. 1085 // NOTE: logout will always be false for a non-HG teleport.
1064 bool logout = false; 1086 bool logout = false;
1065 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 1087 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout))
1066 { 1088 {
1067 m_interRegionTeleportFailures.Value++; 1089 m_interRegionTeleportFailures.Value++;
1068 1090
@@ -1099,32 +1121,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1099 // Past this point we have to attempt clean up if the teleport fails, so update transfer state. 1121 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
1100 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); 1122 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
1101 1123
1102 IClientIPEndpoint ipepClient;
1103 string capsPath = String.Empty;
1104 float dist = (float)Math.Max(sp.Scene.DefaultDrawDistance,
1105 (float)Math.Max(sp.Scene.RegionInfo.RegionSizeX, sp.Scene.RegionInfo.RegionSizeY));
1106 if (NeedsNewAgent(dist, oldRegionX, newRegionX, oldRegionY, newRegionY))
1107 {
1108 m_log.DebugFormat(
1109 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
1110 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
1111
1112 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
1113 #region IP Translation for NAT
1114 // Uses ipepClient above
1115 if (sp.ClientView.TryGet(out ipepClient))
1116 {
1117 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1118 }
1119 #endregion
1120 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1121 }
1122 else
1123 {
1124 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
1125 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1126 }
1127
1128 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator, 1124 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
1129 // where that neighbour simulator could otherwise request a child agent create on the source which then 1125 // where that neighbour simulator could otherwise request a child agent create on the source which then
1130 // closes our existing agent which is still signalled as root. 1126 // closes our existing agent which is still signalled as root.
@@ -1146,6 +1142,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1146 AgentData agent = new AgentData(); 1142 AgentData agent = new AgentData();
1147 sp.CopyTo(agent); 1143 sp.CopyTo(agent);
1148 agent.Position = agentCircuit.startpos; 1144 agent.Position = agentCircuit.startpos;
1145
1146 if ((teleportFlags & (uint)TeleportFlags.IsFlying) != 0)
1147 agent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1148
1149 agent.SenderWantsToWaitForRoot = true; 1149 agent.SenderWantsToWaitForRoot = true;
1150 //SetCallbackURL(agent, sp.Scene.RegionInfo); 1150 //SetCallbackURL(agent, sp.Scene.RegionInfo);
1151 1151
@@ -1158,7 +1158,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1158 // Send the Update. If this returns true, we know the client has contacted the destination 1158 // Send the Update. If this returns true, we know the client has contacted the destination
1159 // via CompleteMovementIntoRegion, so we can let go. 1159 // via CompleteMovementIntoRegion, so we can let go.
1160 // If it returns false, something went wrong, and we need to abort. 1160 // If it returns false, something went wrong, and we need to abort.
1161 if (!UpdateAgent(reg, finalDestination, agent, sp)) 1161 if (!UpdateAgent(reg, finalDestination, agent, sp, ctx))
1162 { 1162 {
1163 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) 1163 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1164 { 1164 {
@@ -1187,19 +1187,21 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1187 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex 1187 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex
1188 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are 1188 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are
1189 // abandoned without proper close by viewer but then re-used by an incoming connection. 1189 // abandoned without proper close by viewer but then re-used by an incoming connection.
1190 sp.CloseChildAgents(newRegionX, newRegionY); 1190 sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1191 1191
1192 // May need to logout or other cleanup 1192 sp.HasMovedAway(!(OutSideViewRange || logout));
1193 AgentHasMovedAway(sp, logout);
1194 1193
1195 // Well, this is it. The agent is over there. 1194 //HG hook
1196 KillEntity(sp.Scene, sp.LocalId); 1195 AgentHasMovedAway(sp, logout);
1197 1196
1198 // Now let's make it officially a child agent 1197 // Now let's make it officially a child agent
1199 sp.MakeChildAgent(); 1198 sp.MakeChildAgent(destinationHandle);
1199
1200
1200 1201
1201 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1202 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1202 if (NeedsClosing(sp.Scene.DefaultDrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1203 // go by HG hook
1204 if (NeedsClosing(reg, OutSideViewRange))
1203 { 1205 {
1204 if (!sp.Scene.IncomingPreCloseClient(sp)) 1206 if (!sp.Scene.IncomingPreCloseClient(sp))
1205 return; 1207 return;
@@ -1210,8 +1212,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1210 // BEFORE THEY SETTLE IN THE NEW REGION. 1212 // BEFORE THEY SETTLE IN THE NEW REGION.
1211 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR 1213 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR
1212 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS. 1214 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS.
1213 Thread.Sleep(15000); 1215
1214 1216 Thread.Sleep(14000);
1217 if (m_eqModule != null && !sp.DoNotCloseAfterTeleport)
1218 m_eqModule.DisableSimulator(sp.RegionHandle,sp.UUID);
1219 Thread.Sleep(1000);
1220
1215 // OK, it got this agent. Let's close everything 1221 // OK, it got this agent. Let's close everything
1216 // If we shouldn't close the agent due to some other region renewing the connection 1222 // If we shouldn't close the agent due to some other region renewing the connection
1217 // then this will be handled in IncomingCloseAgent under lock conditions 1223 // then this will be handled in IncomingCloseAgent under lock conditions
@@ -1220,11 +1226,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1220 1226
1221 sp.Scene.CloseAgent(sp.UUID, false); 1227 sp.Scene.CloseAgent(sp.UUID, false);
1222 } 1228 }
1229/*
1223 else 1230 else
1224 { 1231 {
1225 // now we have a child agent in this region. 1232 // now we have a child agent in this region.
1226 sp.Reset(); 1233 sp.Reset();
1227 } 1234 }
1235 */
1228 } 1236 }
1229 1237
1230 /// <summary> 1238 /// <summary>
@@ -1272,13 +1280,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1272 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); 1280 sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
1273 } 1281 }
1274 1282
1275 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 1283 protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
1276 { 1284 {
1277 GridRegion source = new GridRegion(Scene.RegionInfo); 1285 GridRegion source = new GridRegion(Scene.RegionInfo);
1278 source.RawServerURI = m_GatekeeperURI; 1286 source.RawServerURI = m_GatekeeperURI;
1279 1287
1280 logout = false; 1288 logout = false;
1281 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, out reason); 1289 bool success = Scene.SimulationService.CreateAgent(source, finalDestination, agentCircuit, teleportFlags, ctx, out reason);
1282 1290
1283 if (success) 1291 if (success)
1284 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout); 1292 sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout);
@@ -1286,9 +1294,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1286 return success; 1294 return success;
1287 } 1295 }
1288 1296
1289 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) 1297 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp, EntityTransferContext ctx)
1290 { 1298 {
1291 return Scene.SimulationService.UpdateAgent(finalDestination, agent); 1299 return Scene.SimulationService.UpdateAgent(finalDestination, agent, ctx);
1292 } 1300 }
1293 1301
1294 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region) 1302 protected virtual void SetCallbackURL(AgentData agent, RegionInfo region)
@@ -1305,10 +1313,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1305 /// </summary> 1313 /// </summary>
1306 /// <param name='sp'></param> 1314 /// <param name='sp'></param>
1307 /// <param name='logout'></param> 1315 /// <param name='logout'></param>
1316 ///
1317 /// now just a HG hook
1308 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout) 1318 protected virtual void AgentHasMovedAway(ScenePresence sp, bool logout)
1309 { 1319 {
1310 if (sp.Scene.AttachmentsModule != null) 1320// if (sp.Scene.AttachmentsModule != null)
1311 sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, true); 1321// sp.Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, logout);
1312 } 1322 }
1313 1323
1314 protected void KillEntity(Scene scene, uint localID) 1324 protected void KillEntity(Scene scene, uint localID)
@@ -1316,6 +1326,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1316 scene.SendKillObject(new List<uint> { localID }); 1326 scene.SendKillObject(new List<uint> { localID });
1317 } 1327 }
1318 1328
1329 // HG hook
1319 protected virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message) 1330 protected virtual GridRegion GetFinalDestination(GridRegion region, UUID agentID, string agentHomeURI, out string message)
1320 { 1331 {
1321 message = null; 1332 message = null;
@@ -1325,7 +1336,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1325 // This returns 'true' if the new region already has a child agent for our 1336 // This returns 'true' if the new region already has a child agent for our
1326 // incoming agent. The implication is that, if 'false', we have to create the 1337 // incoming agent. The implication is that, if 'false', we have to create the
1327 // child and then teleport into the region. 1338 // child and then teleport into the region.
1328 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY) 1339 protected virtual bool NeedsNewAgent(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY,
1340 int oldsizeX, int oldsizeY, int newsizeX, int newsizeY)
1329 { 1341 {
1330 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 1342 if (m_regionCombinerModule != null && m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
1331 { 1343 {
@@ -1338,15 +1350,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1338 1350
1339 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y); 1351 return !(newRegionX >= swCorner.X && newRegionX <= neCorner.X && newRegionY >= swCorner.Y && newRegionY <= neCorner.Y);
1340 } 1352 }
1341 else 1353
1342 { 1354 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY,
1343 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1355 oldsizeX, oldsizeY, newsizeX, newsizeY);
1344 }
1345 } 1356 }
1346 1357
1347 protected virtual bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 1358 // HG Hook
1359 protected virtual bool NeedsClosing(GridRegion reg, bool OutViewRange)
1360
1348 { 1361 {
1349 return Util.IsOutsideView(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY); 1362 return OutViewRange;
1350 } 1363 }
1351 1364
1352 #endregion 1365 #endregion
@@ -1429,105 +1442,143 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1429 1442
1430 #region Agent Crossings 1443 #region Agent Crossings
1431 1444
1432 // Given a position relative to the current region (which has previously been tested to 1445 public bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position,
1433 // see that it is actually outside the current region), find the new region that the 1446 EntityTransferContext ctx, out string reason)
1434 // point is actually in. 1447 {
1435 // Returns the coordinates and information of the new region or 'null' of it doesn't exist. 1448 reason = String.Empty;
1449
1450 UUID agentID = agent.UUID;
1451 ulong destinyHandle = destiny.RegionHandle;
1452
1453 if (m_bannedRegionCache.IfBanned(destinyHandle, agentID))
1454 {
1455 return false;
1456 }
1457
1458 Scene ascene = agent.Scene;
1459 string homeURI = ascene.GetAgentHomeURI(agentID);
1460
1461
1462 if (!ascene.SimulationService.QueryAccess(destiny, agentID, homeURI, false, position,
1463 agent.Scene.GetFormatsOffered(), ctx, out reason))
1464 {
1465 m_bannedRegionCache.Add(destinyHandle, agentID, 30.0, 30.0);
1466 return false;
1467 }
1468 return true;
1469 }
1470
1471 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx, out Vector3 newpos)
1472 {
1473 string r = String.Empty;
1474 return GetDestination(scene, agentID, pos, ctx, out newpos, out r);
1475 }
1476
1477 // Given a position relative to the current region and outside of it
1478 // find the new region that the point is actually in.
1479 // returns 'null' if new region not found or if information
1480 // and new position relative to it
1481 // now only works for crossings
1482
1436 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, 1483 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos,
1437 EntityTransferContext ctx, out Vector3 newpos, out string failureReason) 1484 EntityTransferContext ctx, out Vector3 newpos, out string failureReason)
1438 { 1485 {
1439 newpos = pos; 1486 newpos = pos;
1440 failureReason = string.Empty; 1487 failureReason = string.Empty;
1441 string homeURI = scene.GetAgentHomeURI(agentID);
1442 1488
1443// m_log.DebugFormat( 1489// m_log.DebugFormat(
1444// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1490// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
1445 1491
1446 // Compute world location of the object's position 1492 // Compute world location of the agente position
1447 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X; 1493 double presenceWorldX = (double)scene.RegionInfo.WorldLocX + pos.X;
1448 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y; 1494 double presenceWorldY = (double)scene.RegionInfo.WorldLocY + pos.Y;
1449 1495
1450 // Call the grid service to lookup the region containing the new position. 1496 // Call the grid service to lookup the region containing the new position.
1451 GridRegion neighbourRegion = GetRegionContainingWorldLocation(scene.GridService, scene.RegionInfo.ScopeID, 1497 GridRegion neighbourRegion = GetRegionContainingWorldLocation(
1452 presenceWorldX, presenceWorldY, 1498 scene.GridService, scene.RegionInfo.ScopeID,
1453 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY)); 1499 presenceWorldX, presenceWorldY,
1500 Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY));
1454 1501
1455 if (neighbourRegion != null) 1502 if (neighbourRegion == null)
1456 { 1503 {
1457 // Compute the entity's position relative to the new region 1504 return null;
1458 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX), 1505 }
1506 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID))
1507 {
1508 return null;
1509 }
1510
1511 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1512
1513 // Compute the entity's position relative to the new region
1514 newpos = new Vector3((float)(presenceWorldX - (double)neighbourRegion.RegionLocX),
1459 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY), 1515 (float)(presenceWorldY - (double)neighbourRegion.RegionLocY),
1460 pos.Z); 1516 pos.Z);
1461 1517
1462 if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID)) 1518 string homeURI = scene.GetAgentHomeURI(agentID);
1463 {
1464 failureReason = "Cannot region cross into banned parcel";
1465 neighbourRegion = null;
1466 }
1467 else
1468 {
1469 // If not banned, make sure this agent is not in the list.
1470 m_bannedRegionCache.Remove(neighbourRegion.RegionHandle, agentID);
1471 }
1472 1519
1473 // Check to see if we have access to the target region. 1520 if (!scene.SimulationService.QueryAccess(
1474 if (neighbourRegion != null 1521 neighbourRegion, agentID, homeURI, false, newpos,
1475 && !scene.SimulationService.QueryAccess(neighbourRegion, agentID, homeURI, false, newpos, scene.GetFormatsOffered(), ctx, out failureReason)) 1522 scene.GetFormatsOffered(), ctx, out failureReason))
1476 {
1477 // remember banned
1478 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1479 neighbourRegion = null;
1480 }
1481 }
1482 else
1483 { 1523 {
1484 // The destination region just doesn't exist 1524 // remember the fail
1485 failureReason = "Cannot cross into non-existent region"; 1525 m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID);
1526 return null;
1486 } 1527 }
1487 1528
1488 if (neighbourRegion == null)
1489 m_log.DebugFormat("{0} GetDestination: region not found. Old region name={1} at <{2},{3}> of size <{4},{5}>. Old pos={6}",
1490 LogHeader, scene.RegionInfo.RegionName,
1491 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
1492 scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY,
1493 pos);
1494 else
1495 m_log.DebugFormat("{0} GetDestination: new region={1} at <{2},{3}> of size <{4},{5}>, newpos=<{6},{7}>",
1496 LogHeader, neighbourRegion.RegionName,
1497 neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY,
1498 newpos.X, newpos.Y);
1499
1500 return neighbourRegion; 1529 return neighbourRegion;
1501 } 1530 }
1502 1531
1503 public bool Cross(ScenePresence agent, bool isFlying) 1532 public bool Cross(ScenePresence agent, bool isFlying)
1504 { 1533 {
1534 agent.IsInTransit = true;
1535 CrossAsyncDelegate d = CrossAsync;
1536 d.BeginInvoke(agent, isFlying, CrossCompleted, d);
1537 return true;
1538 }
1539
1540 private void CrossCompleted(IAsyncResult iar)
1541 {
1542 CrossAsyncDelegate icon = (CrossAsyncDelegate)iar.AsyncState;
1543 ScenePresence agent = icon.EndInvoke(iar);
1544
1545 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
1546
1547 if(!agent.IsChildAgent)
1548 {
1549 // crossing failed
1550 agent.CrossToNewRegionFail();
1551 }
1552 agent.IsInTransit = false;
1553 }
1554
1555 public ScenePresence CrossAsync(ScenePresence agent, bool isFlying)
1556 {
1557 uint x;
1558 uint y;
1505 Vector3 newpos; 1559 Vector3 newpos;
1506 EntityTransferContext ctx = new EntityTransferContext(); 1560 EntityTransferContext ctx = new EntityTransferContext();
1507 string failureReason; 1561 string failureReason;
1508 1562
1509 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, 1563 Vector3 pos = agent.AbsolutePosition + agent.Velocity;
1564
1565 GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, pos,
1510 ctx, out newpos, out failureReason); 1566 ctx, out newpos, out failureReason);
1511 if (neighbourRegion == null) 1567 if (neighbourRegion == null)
1512 { 1568 {
1513 agent.ControllingClient.SendAlertMessage(failureReason); 1569 if (failureReason != String.Empty)
1514 return false; 1570 agent.ControllingClient.SendAlertMessage(failureReason);
1571 return agent;
1515 } 1572 }
1516 1573
1517 agent.IsInTransit = true; 1574// agent.IsInTransit = true;
1518 1575
1519 CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; 1576 CrossAgentToNewRegionAsync(agent, newpos, neighbourRegion, isFlying, ctx);
1520 d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, ctx, CrossAgentToNewRegionCompleted, d); 1577 agent.IsInTransit = false;
1521 1578 return agent;
1522 Scene.EventManager.TriggerCrossAgentToNewRegion(agent, isFlying, neighbourRegion);
1523
1524 return true;
1525 } 1579 }
1526 1580
1527 1581 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene);
1528 public delegate void InformClientToInitiateTeleportToLocationDelegate(ScenePresence agent, uint regionX, uint regionY,
1529 Vector3 position,
1530 Scene initiatingScene);
1531 1582
1532 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene) 1583 private void InformClientToInitiateTeleportToLocation(ScenePresence agent, uint regionX, uint regionY, Vector3 position, Scene initiatingScene)
1533 { 1584 {
@@ -1628,7 +1679,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1628 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1679 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1629 } 1680 }
1630 1681
1631 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) 1682 if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying, ctx))
1632 { 1683 {
1633 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader); 1684 m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader);
1634 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1685 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
@@ -1644,14 +1695,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1644 return agent; 1695 return agent;
1645 } 1696 }
1646 1697
1647 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying) 1698 public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx)
1648 { 1699 {
1700 int ts = Util.EnvironmentTickCount();
1649 try 1701 try
1650 { 1702 {
1651 AgentData cAgent = new AgentData(); 1703 AgentData cAgent = new AgentData();
1652 agent.CopyTo(cAgent); 1704 agent.CopyTo(cAgent);
1705
1706// agent.Appearance.WearableCacheItems = null;
1707
1653 cAgent.Position = pos; 1708 cAgent.Position = pos;
1654 1709
1710 cAgent.ChildrenCapSeeds = agent.KnownRegions;
1711
1655 if (isFlying) 1712 if (isFlying)
1656 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; 1713 cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
1657 1714
@@ -1661,7 +1718,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1661 // Beyond this point, extra cleanup is needed beyond removing transit state 1718 // Beyond this point, extra cleanup is needed beyond removing transit state
1662 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); 1719 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring);
1663 1720
1664 if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) 1721 if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent, ctx))
1665 { 1722 {
1666 // region doesn't take it 1723 // region doesn't take it
1667 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1724 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
@@ -1671,11 +1728,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1671 neighbourRegion.RegionName, agent.Name); 1728 neighbourRegion.RegionName, agent.Name);
1672 1729
1673 ReInstantiateScripts(agent); 1730 ReInstantiateScripts(agent);
1674 agent.AddToPhysicalScene(isFlying); 1731 if(agent.ParentID == 0 && agent.ParentUUID == UUID.Zero)
1732 agent.AddToPhysicalScene(isFlying);
1675 1733
1676 return false; 1734 return false;
1677 } 1735 }
1678 1736
1737 m_log.DebugFormat("[CrossAgentIntoNewRegionMain] ok, time {0}ms",Util.EnvironmentTickCountSubtract(ts));
1738
1679 } 1739 }
1680 catch (Exception e) 1740 catch (Exception e)
1681 { 1741 {
@@ -1693,7 +1753,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1693 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, 1753 public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion,
1694 bool isFlying, EntityTransferContext ctx) 1754 bool isFlying, EntityTransferContext ctx)
1695 { 1755 {
1696 agent.ControllingClient.RequestClientInfo();
1697 1756
1698 string agentcaps; 1757 string agentcaps;
1699 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) 1758 if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
@@ -1704,6 +1763,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1704 } 1763 }
1705 1764
1706 // No turning back 1765 // No turning back
1766
1707 agent.IsChildAgent = true; 1767 agent.IsChildAgent = true;
1708 1768
1709 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); 1769 string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps);
@@ -1715,7 +1775,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1715 if (m_eqModule != null) 1775 if (m_eqModule != null)
1716 { 1776 {
1717 m_eqModule.CrossRegion( 1777 m_eqModule.CrossRegion(
1718 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, 1778 neighbourRegion.RegionHandle, pos, vel2 /* agent.Velocity */,
1719 neighbourRegion.ExternalEndPoint, 1779 neighbourRegion.ExternalEndPoint,
1720 capsPath, agent.UUID, agent.ControllingClient.SessionId, 1780 capsPath, agent.UUID, agent.ControllingClient.SessionId,
1721 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); 1781 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
@@ -1723,25 +1783,36 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1723 else 1783 else
1724 { 1784 {
1725 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader); 1785 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader);
1726 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, 1786 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
1727 capsPath); 1787 capsPath);
1728 } 1788 }
1729 1789
1790/*
1791 // Backwards compatibility. Best effort
1792 if (version == 0f)
1793 {
1794 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one...");
1795 Thread.Sleep(3000); // wait a little now that we're not waiting for the callback
1796 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1797 }
1798*/
1730 // SUCCESS! 1799 // SUCCESS!
1731 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); 1800 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination);
1732 1801
1733 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. 1802 // Unlike a teleport, here we do not wait for the destination region to confirm the receipt.
1734 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); 1803 m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp);
1735 1804
1736 agent.MakeChildAgent(); 1805 // this may need the attachments
1806
1807 agent.HasMovedAway(true);
1808
1809 agent.MakeChildAgent(neighbourRegion.RegionHandle);
1737 1810
1738 // FIXME: Possibly this should occur lower down after other commands to close other agents, 1811 // FIXME: Possibly this should occur lower down after other commands to close other agents,
1739 // but not sure yet what the side effects would be. 1812 // but not sure yet what the side effects would be.
1740 m_entityTransferStateMachine.ResetFromTransit(agent.UUID); 1813 m_entityTransferStateMachine.ResetFromTransit(agent.UUID);
1741 1814
1742 // now we have a child agent in this region. Request all interesting data about other (root) agents 1815 agent.CloseChildAgents(false, neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1743 agent.SendOtherAgentsAvatarDataToClient();
1744 agent.SendOtherAgentsAppearanceToClient();
1745 1816
1746 // TODO: Check since what version this wasn't needed anymore. May be as old as 0.6 1817 // TODO: Check since what version this wasn't needed anymore. May be as old as 0.6
1747/* 1818/*
@@ -1753,14 +1824,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1753 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); 1824 CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true);
1754 } 1825 }
1755*/ 1826*/
1756 // Next, let's close the child agent connections that are too far away.
1757 uint neighbourx;
1758 uint neighboury;
1759 Util.RegionHandleToRegionLoc(neighbourRegion.RegionHandle, out neighbourx, out neighboury);
1760
1761 agent.CloseChildAgents(neighbourx, neighboury);
1762
1763 AgentHasMovedAway(agent, false);
1764 1827
1765 // the user may change their profile information in other region, 1828 // the user may change their profile information in other region,
1766 // so the userinfo in UserProfileCache is not reliable any more, delete it 1829 // so the userinfo in UserProfileCache is not reliable any more, delete it
@@ -1800,7 +1863,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1800 #region Enable Child Agent 1863 #region Enable Child Agent
1801 1864
1802 /// <summary> 1865 /// <summary>
1803 /// This informs a single neighbouring region about agent "avatar". 1866 /// This informs a single neighbouring region about agent "avatar", and avatar about it
1804 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 1867 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
1805 /// </summary> 1868 /// </summary>
1806 /// <param name="sp"></param> 1869 /// <param name="sp"></param>
@@ -1809,41 +1872,47 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1809 { 1872 {
1810 m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName); 1873 m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighbour {0}", region.RegionName);
1811 1874
1875 ulong currentRegionHandler = sp.Scene.RegionInfo.RegionHandle;
1876 ulong regionhandler = region.RegionHandle;
1877
1878 Dictionary<ulong, string> seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1879
1880 if (seeds.ContainsKey(regionhandler))
1881 seeds.Remove(regionhandler);
1882/*
1883 List<ulong> oldregions = new List<ulong>(seeds.Keys);
1884
1885 if (oldregions.Contains(currentRegionHandler))
1886 oldregions.Remove(currentRegionHandler);
1887*/
1888 if (!seeds.ContainsKey(currentRegionHandler))
1889 seeds.Add(currentRegionHandler, sp.ControllingClient.RequestClientInfo().CapsPath);
1890
1812 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 1891 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1813 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 1892 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo();
1814 agent.BaseFolder = UUID.Zero; 1893 agent.BaseFolder = UUID.Zero;
1815 agent.InventoryFolder = UUID.Zero; 1894 agent.InventoryFolder = UUID.Zero;
1816 agent.startpos = new Vector3(128, 128, 70); 1895 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, region);
1817 agent.child = true; 1896 agent.child = true;
1818 agent.Appearance = sp.Appearance; 1897 agent.Appearance = new AvatarAppearance();
1898 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1899
1819 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 1900 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1820 1901
1821 agent.ChildrenCapSeeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID)); 1902 seeds.Add(regionhandler, agent.CapsPath);
1822 //m_log.DebugFormat("[XXX] Seeds 1 {0}", agent.ChildrenCapSeeds.Count);
1823 1903
1824 if (!agent.ChildrenCapSeeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle))
1825 agent.ChildrenCapSeeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1826 //m_log.DebugFormat("[XXX] Seeds 2 {0}", agent.ChildrenCapSeeds.Count);
1827 1904
1828 sp.AddNeighbourRegion(region.RegionHandle, agent.CapsPath); 1905// agent.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1829 //foreach (ulong h in agent.ChildrenCapSeeds.Keys) 1906 agent.ChildrenCapSeeds = null;
1830 // m_log.DebugFormat("[XXX] --> {0}", h);
1831 //m_log.DebugFormat("[XXX] Adding {0}", region.RegionHandle);
1832 if (agent.ChildrenCapSeeds.ContainsKey(region.RegionHandle))
1833 {
1834 m_log.WarnFormat(
1835 "[ENTITY TRANSFER]: Overwriting caps seed {0} with {1} for region {2} (handle {3}) for {4} in {5}",
1836 agent.ChildrenCapSeeds[region.RegionHandle], agent.CapsPath,
1837 region.RegionName, region.RegionHandle, sp.Name, Scene.Name);
1838 }
1839
1840 agent.ChildrenCapSeeds[region.RegionHandle] = agent.CapsPath;
1841 1907
1842 if (sp.Scene.CapsModule != null) 1908 if (sp.Scene.CapsModule != null)
1843 { 1909 {
1844 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, agent.ChildrenCapSeeds); 1910 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1845 } 1911 }
1846 1912
1913 sp.KnownRegions = seeds;
1914 sp.AddNeighbourRegionSizeInfo(region);
1915
1847 if (currentAgentCircuit != null) 1916 if (currentAgentCircuit != null)
1848 { 1917 {
1849 agent.ServiceURLs = currentAgentCircuit.ServiceURLs; 1918 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
@@ -1853,7 +1922,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1853 agent.Mac = currentAgentCircuit.Mac; 1922 agent.Mac = currentAgentCircuit.Mac;
1854 agent.Id0 = currentAgentCircuit.Id0; 1923 agent.Id0 = currentAgentCircuit.Id0;
1855 } 1924 }
1856 1925/*
1926 AgentPosition agentpos = null;
1927
1928 if (oldregions.Count > 0)
1929 {
1930 agentpos = new AgentPosition();
1931 agentpos.AgentID = new UUID(sp.UUID.Guid);
1932 agentpos.SessionID = sp.ControllingClient.SessionId;
1933 agentpos.Size = sp.Appearance.AvatarSize;
1934 agentpos.Center = sp.CameraPosition;
1935 agentpos.Far = sp.DrawDistance;
1936 agentpos.Position = sp.AbsolutePosition;
1937 agentpos.Velocity = sp.Velocity;
1938 agentpos.RegionHandle = currentRegionHandler;
1939 agentpos.Throttles = sp.ControllingClient.GetThrottlesPacked(1);
1940 agentpos.ChildrenCapSeeds = seeds;
1941 }
1942*/
1857 IPEndPoint external = region.ExternalEndPoint; 1943 IPEndPoint external = region.ExternalEndPoint;
1858 if (external != null) 1944 if (external != null)
1859 { 1945 {
@@ -1862,7 +1948,23 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1862 InformClientOfNeighbourCompleted, 1948 InformClientOfNeighbourCompleted,
1863 d); 1949 d);
1864 } 1950 }
1951/*
1952 if(oldregions.Count >0)
1953 {
1954 uint neighbourx;
1955 uint neighboury;
1956 UUID scope = sp.Scene.RegionInfo.ScopeID;
1957 foreach (ulong handler in oldregions)
1958 {
1959 // crap code
1960 Utils.LongToUInts(handler, out neighbourx, out neighboury);
1961 GridRegion neighbour = sp.Scene.GridService.GetRegionByPosition(scope, (int)neighbourx, (int)neighboury);
1962 sp.Scene.SimulationService.UpdateAgent(neighbour, agentpos);
1963 }
1964 }
1965 */
1865 } 1966 }
1967
1866 #endregion 1968 #endregion
1867 1969
1868 #region Enable Child Agents 1970 #region Enable Child Agents
@@ -1872,146 +1974,153 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1872 1974
1873 /// <summary> 1975 /// <summary>
1874 /// This informs all neighbouring regions about agent "avatar". 1976 /// This informs all neighbouring regions about agent "avatar".
1977 /// and as important informs the avatar about then
1875 /// </summary> 1978 /// </summary>
1876 /// <param name="sp"></param> 1979 /// <param name="sp"></param>
1877 public void EnableChildAgents(ScenePresence sp) 1980 public void EnableChildAgents(ScenePresence sp)
1878 { 1981 {
1982 // assumes that out of view range regions are disconnected by the previus region
1983
1879 List<GridRegion> neighbours = new List<GridRegion>(); 1984 List<GridRegion> neighbours = new List<GridRegion>();
1880 RegionInfo m_regionInfo = sp.Scene.RegionInfo; 1985 Scene spScene = sp.Scene;
1986 RegionInfo m_regionInfo = spScene.RegionInfo;
1881 1987
1882 if (m_regionInfo != null) 1988 if (m_regionInfo != null)
1883 { 1989 {
1884 neighbours = GetNeighbours(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); 1990 neighbours = GetNeighbors(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
1885 } 1991 }
1886 else 1992 else
1887 { 1993 {
1888 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?"); 1994 m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?");
1889 } 1995 }
1890 1996
1891 /// We need to find the difference between the new regions where there are no child agents 1997 ulong currentRegionHandler = m_regionInfo.RegionHandle;
1892 /// and the regions where there are already child agents. We only send notification to the former.
1893 List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
1894 neighbourHandles.Add(sp.Scene.RegionInfo.RegionHandle); // add this region too
1895 List<ulong> previousRegionNeighbourHandles;
1896 1998
1897 if (sp.Scene.CapsModule != null) 1999 LinkedList<ulong> previousRegionNeighbourHandles;
2000 Dictionary<ulong, string> seeds;
2001 ICapabilitiesModule capsModule = spScene.CapsModule;
2002
2003 if (capsModule != null)
1898 { 2004 {
1899 previousRegionNeighbourHandles = 2005 seeds = new Dictionary<ulong, string>(capsModule.GetChildrenSeeds(sp.UUID));
1900 new List<ulong>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID).Keys); 2006 previousRegionNeighbourHandles = new LinkedList<ulong>(seeds.Keys);
1901 } 2007 }
1902 else 2008 else
1903 { 2009 {
1904 previousRegionNeighbourHandles = new List<ulong>(); 2010 seeds = new Dictionary<ulong, string>();
2011 previousRegionNeighbourHandles = new LinkedList<ulong>();
1905 } 2012 }
1906 2013
1907 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles); 2014 IClientAPI spClient = sp.ControllingClient;
1908 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1909
1910// Dump("Current Neighbors", neighbourHandles);
1911// Dump("Previous Neighbours", previousRegionNeighbourHandles);
1912// Dump("New Neighbours", newRegions);
1913// Dump("Old Neighbours", oldRegions);
1914 2015
1915 /// Update the scene presence's known regions here on this region 2016 if (!seeds.ContainsKey(currentRegionHandler))
1916 sp.DropOldNeighbours(oldRegions); 2017 seeds.Add(currentRegionHandler, spClient.RequestClientInfo().CapsPath);
1917
1918 /// Collect as many seeds as possible
1919 Dictionary<ulong, string> seeds;
1920 if (sp.Scene.CapsModule != null)
1921 seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1922 else
1923 seeds = new Dictionary<ulong, string>();
1924 2018
1925 //m_log.Debug(" !!! No. of seeds: " + seeds.Count); 2019 AgentCircuitData currentAgentCircuit =
1926 if (!seeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle)) 2020 spScene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1927 seeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath);
1928 2021
1929 /// Create the necessary child agents
1930 List<AgentCircuitData> cagents = new List<AgentCircuitData>(); 2022 List<AgentCircuitData> cagents = new List<AgentCircuitData>();
2023 List<ulong> newneighbours = new List<ulong>();
2024
1931 foreach (GridRegion neighbour in neighbours) 2025 foreach (GridRegion neighbour in neighbours)
1932 { 2026 {
1933 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2027 ulong handler = neighbour.RegionHandle;
2028
2029 if (previousRegionNeighbourHandles.Contains(handler))
1934 { 2030 {
1935 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 2031 // agent already knows this region
1936 AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); 2032 previousRegionNeighbourHandles.Remove(handler);
1937 agent.BaseFolder = UUID.Zero; 2033 continue;
1938 agent.InventoryFolder = UUID.Zero; 2034 }
1939 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1940 agent.child = true;
1941 agent.Appearance = sp.Appearance;
1942 if (currentAgentCircuit != null)
1943 {
1944 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
1945 agent.IPAddress = currentAgentCircuit.IPAddress;
1946 agent.Viewer = currentAgentCircuit.Viewer;
1947 agent.Channel = currentAgentCircuit.Channel;
1948 agent.Mac = currentAgentCircuit.Mac;
1949 agent.Id0 = currentAgentCircuit.Id0;
1950 }
1951 2035
1952 if (newRegions.Contains(neighbour.RegionHandle)) 2036 if (handler == currentRegionHandler)
1953 { 2037 continue;
1954 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 2038
1955 sp.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath); 2039 // a new region to add
1956 seeds.Add(neighbour.RegionHandle, agent.CapsPath); 2040 AgentCircuitData agent = spClient.RequestClientInfo();
1957 } 2041 agent.BaseFolder = UUID.Zero;
1958 else 2042 agent.InventoryFolder = UUID.Zero;
1959 { 2043 agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour);
1960 agent.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, neighbour.RegionHandle); 2044 agent.child = true;
1961 } 2045 agent.Appearance = new AvatarAppearance();
2046 agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight;
1962 2047
1963 cagents.Add(agent); 2048 if (currentAgentCircuit != null)
2049 {
2050 agent.ServiceURLs = currentAgentCircuit.ServiceURLs;
2051 agent.IPAddress = currentAgentCircuit.IPAddress;
2052 agent.Viewer = currentAgentCircuit.Viewer;
2053 agent.Channel = currentAgentCircuit.Channel;
2054 agent.Mac = currentAgentCircuit.Mac;
2055 agent.Id0 = currentAgentCircuit.Id0;
1964 } 2056 }
1965 }
1966 2057
1967 /// Update all child agent with everyone's seeds 2058 newneighbours.Add(handler);
1968 foreach (AgentCircuitData a in cagents) 2059 agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
1969 { 2060 seeds.Add(handler, agent.CapsPath);
1970 a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1971 }
1972 2061
1973 if (sp.Scene.CapsModule != null) 2062 agent.ChildrenCapSeeds = null;
1974 { 2063 cagents.Add(agent);
1975 sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, seeds);
1976 } 2064 }
1977 sp.KnownRegions = seeds;
1978 //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
1979 //avatar.DumpKnownRegions();
1980 2065
1981 bool newAgent = false; 2066 if (previousRegionNeighbourHandles.Contains(currentRegionHandler))
1982 int count = 0; 2067 previousRegionNeighbourHandles.Remove(currentRegionHandler);
1983 foreach (GridRegion neighbour in neighbours) 2068
1984 { 2069 // previousRegionNeighbourHandles now contains regions to forget
1985 //m_log.WarnFormat("--> Going to send child agent to {0}", neighbour.RegionName); 2070 foreach (ulong handler in previousRegionNeighbourHandles)
1986 // Don't do it if there's already an agent in that region 2071 seeds.Remove(handler);
1987 if (newRegions.Contains(neighbour.RegionHandle)) 2072
1988 newAgent = true; 2073 /// Update all child agent with everyone's seeds
1989 else 2074 // foreach (AgentCircuitData a in cagents)
1990 newAgent = false; 2075 // a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
1991// continue; 2076
2077 if (capsModule != null)
2078 capsModule.SetChildrenSeed(sp.UUID, seeds);
1992 2079
1993 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 2080 sp.KnownRegions = seeds;
2081 sp.SetNeighbourRegionSizeInfo(neighbours);
2082
2083 AgentPosition agentpos = new AgentPosition();
2084 agentpos.AgentID = new UUID(sp.UUID.Guid);
2085 agentpos.SessionID = spClient.SessionId;
2086 agentpos.Size = sp.Appearance.AvatarSize;
2087 agentpos.Center = sp.CameraPosition;
2088 agentpos.Far = sp.DrawDistance;
2089 agentpos.Position = sp.AbsolutePosition;
2090 agentpos.Velocity = sp.Velocity;
2091 agentpos.RegionHandle = currentRegionHandler;
2092 agentpos.Throttles = spClient.GetThrottlesPacked(1);
2093 // agentpos.ChildrenCapSeeds = seeds;
2094
2095 Util.FireAndForget(delegate
2096 {
2097 Thread.Sleep(200); // the original delay that was at InformClientOfNeighbourAsync start
2098 int count = 0;
2099
2100 foreach (GridRegion neighbour in neighbours)
1994 { 2101 {
2102 ulong handler = neighbour.RegionHandle;
1995 try 2103 try
1996 { 2104 {
1997 // Let's put this back at sync, so that it doesn't clog 2105 if (newneighbours.Contains(handler))
1998 // the network, especially for regions in the same physical server. 2106 {
1999 // We're really not in a hurry here. 2107 InformClientOfNeighbourAsync(sp, cagents[count], neighbour,
2000 InformClientOfNeighbourAsync(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent); 2108 neighbour.ExternalEndPoint, true);
2001 //InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; 2109 count++;
2002 //d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent, 2110 }
2003 // InformClientOfNeighbourCompleted, 2111 else if (!previousRegionNeighbourHandles.Contains(handler))
2004 // d); 2112 {
2113 spScene.SimulationService.UpdateAgent(neighbour, agentpos);
2114 }
2005 } 2115 }
2006
2007 catch (ArgumentOutOfRangeException) 2116 catch (ArgumentOutOfRangeException)
2008 { 2117 {
2009 m_log.ErrorFormat( 2118 m_log.ErrorFormat(
2010 "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbour list. The following region will not display to the client: {0} for region {1} ({2}, {3}).", 2119 "[ENTITY TRANSFER MODULE]: Neighbour Regions response included the current region in the neighbour list. The following region will not display to the client: {0} for region {1} ({2}, {3}).",
2011 neighbour.ExternalHostName, 2120 neighbour.ExternalHostName,
2012 neighbour.RegionHandle, 2121 neighbour.RegionHandle,
2013 neighbour.RegionLocX, 2122 neighbour.RegionLocX,
2014 neighbour.RegionLocY); 2123 neighbour.RegionLocY);
2015 } 2124 }
2016 catch (Exception e) 2125 catch (Exception e)
2017 { 2126 {
@@ -2028,11 +2137,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2028 2137
2029 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes. 2138 // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
2030 // throw e; 2139 // throw e;
2031
2032 } 2140 }
2033 } 2141 }
2034 count++; 2142 });
2035 }
2036 } 2143 }
2037 2144
2038 // Computes the difference between two region bases. 2145 // Computes the difference between two region bases.
@@ -2040,26 +2147,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2040 // The first region is the home region of the passed scene presence. 2147 // The first region is the home region of the passed scene presence.
2041 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour) 2148 Vector3 CalculateOffset(ScenePresence sp, GridRegion neighbour)
2042 { 2149 {
2043 /* 2150 return new Vector3(sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2044 int rRegionX = (int)sp.Scene.RegionInfo.LegacyRegionLocX;
2045 int rRegionY = (int)sp.Scene.RegionInfo.LegacyRegionLocY;
2046 int tRegionX = neighbour.RegionLocX / (int)Constants.RegionSize;
2047 int tRegionY = neighbour.RegionLocY / (int)Constants.RegionSize;
2048 int shiftx = (rRegionX - tRegionX) * (int)Constants.RegionSize;
2049 int shifty = (rRegionY - tRegionY) * (int)Constants.RegionSize;
2050 return new Vector3(shiftx, shifty, 0f);
2051 */
2052 return new Vector3( sp.Scene.RegionInfo.WorldLocX - neighbour.RegionLocX,
2053 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY, 2151 sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY,
2054 0f); 2152 0f);
2055 } 2153 }
2056 2154
2057 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2058 {
2059 // Since we don't know how big the regions could be, we have to search a very large area
2060 // to find possible regions.
2061 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2062 }
2063 2155
2064 #region NotFoundLocationCache class 2156 #region NotFoundLocationCache class
2065 // A collection of not found locations to make future lookups 'not found' lookups quick. 2157 // A collection of not found locations to make future lookups 'not found' lookups quick.
@@ -2144,7 +2236,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2144 #endregion // NotFoundLocationCache class 2236 #endregion // NotFoundLocationCache class
2145 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache(); 2237 private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache();
2146 2238
2147 // Given a world position (fractional meter coordinate), get the GridRegion info for 2239// needed for current OSG or old grid code
2240
2241 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py)
2242 {
2243 // Since we don't know how big the regions could be, we have to search a very large area
2244 // to find possible regions.
2245 return GetRegionContainingWorldLocation(pGridService, pScopeID, px, py, Constants.MaximumRegionSize);
2246 }
2247
2248 // Given a world position, get the GridRegion info for
2148 // the region containing that point. 2249 // the region containing that point.
2149 // Someday this should be a method on GridService. 2250 // Someday this should be a method on GridService.
2150 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere 2251 // 'pSizeHint' is the size of the source region but since the destination point can be anywhere
@@ -2153,7 +2254,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2153 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, 2254 public GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID,
2154 double px, double py, uint pSizeHint) 2255 double px, double py, uint pSizeHint)
2155 { 2256 {
2156 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: query, loc=<{1},{2}>", LogHeader, px, py); 2257 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py);
2157 GridRegion ret = null; 2258 GridRegion ret = null;
2158 const double fudge = 2.0; 2259 const double fudge = 2.0;
2159 2260
@@ -2164,7 +2265,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2164 // thus re-ask the GridService about the location. 2265 // thus re-ask the GridService about the location.
2165 if (m_notFoundLocationCache.Contains(px, py)) 2266 if (m_notFoundLocationCache.Contains(px, py))
2166 { 2267 {
2167 m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py); 2268// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: Not found via cache. loc=<{1},{2}>", LogHeader, px, py);
2168 return null; 2269 return null;
2169 } 2270 }
2170 2271
@@ -2246,55 +2347,60 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2246 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg, 2347 private void InformClientOfNeighbourAsync(ScenePresence sp, AgentCircuitData a, GridRegion reg,
2247 IPEndPoint endPoint, bool newAgent) 2348 IPEndPoint endPoint, bool newAgent)
2248 { 2349 {
2249 // Let's wait just a little to give time to originating regions to catch up with closing child agents
2250 // after a cross here
2251 Thread.Sleep(500);
2252 2350
2253 Scene scene = sp.Scene; 2351 if (newAgent)
2254 2352 {
2255 m_log.DebugFormat( 2353 Scene scene = sp.Scene;
2256 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
2257 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY);
2258 2354
2259 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath); 2355 m_log.DebugFormat(
2356 "[ENTITY TRANSFER MODULE]: Informing {0} {1} about neighbour {2} {3} at ({4},{5})",
2357 sp.Name, sp.UUID, reg.RegionName, endPoint, reg.RegionCoordX, reg.RegionCoordY);
2260 2358
2261 string reason = String.Empty; 2359 string capsPath = reg.ServerURI + CapsUtil.GetCapsSeedPath(a.CapsPath);
2262 2360
2263 bool regionAccepted = scene.SimulationService.CreateAgent(null, reg, a, (uint)TeleportFlags.Default, out reason); 2361 string reason = String.Empty;
2264 2362
2265 if (regionAccepted && newAgent) 2363 EntityTransferContext ctx = new EntityTransferContext();
2266 { 2364 bool regionAccepted = scene.SimulationService.CreateAgent(reg, reg, a, (uint)TeleportFlags.Default, ctx, out reason);
2267 if (m_eqModule != null) 2365
2366 if (regionAccepted)
2268 { 2367 {
2269 #region IP Translation for NAT 2368 // give time for createAgent to finish, since it is async and does grid services access
2270 IClientIPEndpoint ipepClient; 2369 Thread.Sleep(500);
2271 if (sp.ClientView.TryGet(out ipepClient)) 2370
2371 if (m_eqModule != null)
2272 { 2372 {
2273 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); 2373 #region IP Translation for NAT
2274 } 2374 IClientIPEndpoint ipepClient;
2275 #endregion 2375 if (sp.ClientView.TryGet(out ipepClient))
2376 {
2377 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
2378 }
2379 #endregion
2276 2380
2277 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " + 2381 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
2278 "and EstablishAgentCommunication with seed cap {8}", LogHeader, 2382 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
2279 scene.RegionInfo.RegionName, sp.Name, 2383 scene.RegionInfo.RegionName, sp.Name,
2280 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY , capsPath); 2384 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY, capsPath);
2281 2385
2282 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY); 2386 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY);
2283 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY); 2387 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
2284 } 2388 }
2285 else 2389 else
2286 { 2390 {
2287 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint); 2391 sp.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
2288 // TODO: make Event Queue disablable! 2392 // TODO: make Event Queue disablable!
2393 }
2394
2395 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint);
2289 } 2396 }
2290 2397
2291 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Completed inform {0} {1} about neighbour {2}", sp.Name, sp.UUID, endPoint); 2398 if (!regionAccepted)
2399 m_log.WarnFormat(
2400 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2401 reg.RegionName, sp.Name, sp.UUID, reason);
2292 } 2402 }
2293 2403
2294 if (!regionAccepted)
2295 m_log.WarnFormat(
2296 "[ENTITY TRANSFER MODULE]: Region {0} did not accept {1} {2}: {3}",
2297 reg.RegionName, sp.Name, sp.UUID, reason);
2298 } 2404 }
2299 2405
2300 /// <summary> 2406 /// <summary>
@@ -2327,7 +2433,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2327 /// <param name="pRegionLocX"></param> 2433 /// <param name="pRegionLocX"></param>
2328 /// <param name="pRegionLocY"></param> 2434 /// <param name="pRegionLocY"></param>
2329 /// <returns></returns> 2435 /// <returns></returns>
2330 protected List<GridRegion> GetNeighbours(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY) 2436 protected List<GridRegion> GetNeighbors(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY)
2331 { 2437 {
2332 Scene pScene = avatar.Scene; 2438 Scene pScene = avatar.Scene;
2333 RegionInfo m_regionInfo = pScene.RegionInfo; 2439 RegionInfo m_regionInfo = pScene.RegionInfo;
@@ -2338,18 +2444,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2338 // view to include everything in the megaregion 2444 // view to include everything in the megaregion
2339 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID)) 2445 if (m_regionCombinerModule == null || !m_regionCombinerModule.IsRootForMegaregion(Scene.RegionInfo.RegionID))
2340 { 2446 {
2341 // The area to check is as big as the current region. 2447 uint dd = (uint)avatar.DrawDistance;
2342 // We presume all adjacent regions are the same size as this region.
2343 uint dd = Math.Max((uint)avatar.Scene.DefaultDrawDistance,
2344 Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
2345 2448
2346 uint startX = Util.RegionToWorldLoc(pRegionLocX) - dd + Constants.RegionSize/2; 2449 // until avatar movement updates client connections, we need to seend at least this current region imediate Neighbors
2347 uint startY = Util.RegionToWorldLoc(pRegionLocY) - dd + Constants.RegionSize/2; 2450 uint ddX = Math.Max(dd, Constants.RegionSize);
2451 uint ddY = Math.Max(dd, Constants.RegionSize);
2348 2452
2349 uint endX = Util.RegionToWorldLoc(pRegionLocX) + dd + Constants.RegionSize/2; 2453 ddX--;
2350 uint endY = Util.RegionToWorldLoc(pRegionLocY) + dd + Constants.RegionSize/2; 2454 ddY--;
2351 2455
2352 neighbours 2456 // reference to region edges. Should be avatar position
2457 uint startX = Util.RegionToWorldLoc(pRegionLocX);
2458 uint endX = startX + m_regionInfo.RegionSizeX;
2459 uint startY = Util.RegionToWorldLoc(pRegionLocY);
2460 uint endY = startY + m_regionInfo.RegionSizeY;
2461
2462 startX -= ddX;
2463 startY -= ddY;
2464 endX += ddX;
2465 endY += ddY;
2466
2467 neighbours
2353 = avatar.Scene.GridService.GetRegionRange( 2468 = avatar.Scene.GridService.GetRegionRange(
2354 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY); 2469 m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY);
2355 } 2470 }
@@ -2365,72 +2480,70 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2365 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y)); 2480 (int)Util.RegionToWorldLoc((uint)swCorner.Y), (int)Util.RegionToWorldLoc((uint)neCorner.Y));
2366 } 2481 }
2367 2482
2368// neighbours.ForEach(
2369// n =>
2370// m_log.DebugFormat(
2371// "[ENTITY TRANSFER MODULE]: Region flags for {0} as seen by {1} are {2}",
2372// n.RegionName, Scene.Name, n.RegionFlags != null ? n.RegionFlags.ToString() : "not present"));
2373
2374 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1). 2483 // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1).
2375 neighbours.RemoveAll( 2484 neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID );
2376 r =>
2377 r.RegionID == m_regionInfo.RegionID
2378 || (r.RegionFlags != null && (r.RegionFlags & OpenSim.Framework.RegionFlags.RegionOnline) == 0));
2379 2485
2380 return neighbours; 2486 return neighbours;
2381 } 2487 }
2488 #endregion
2489
2490 #region Agent Arrived
2382 2491
2383 private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours) 2492 public void AgentArrivedAtDestination(UUID id)
2384 { 2493 {
2385 return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); }); 2494 m_entityTransferStateMachine.SetAgentArrivedAtDestination(id);
2386 } 2495 }
2387 2496
2388 // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours) 2497 #endregion
2389 // {
2390 // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
2391 // }
2392 2498
2393 private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours) 2499 #region Object Transfers
2394 {
2395 return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
2396 }
2397 2500
2398 private List<ulong> NeighbourHandles(List<GridRegion> neighbours) 2501 public GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition,out Vector3 newpos)
2399 { 2502 {
2400 List<ulong> handles = new List<ulong>(); 2503 newpos = targetPosition;
2401 foreach (GridRegion reg in neighbours) 2504
2505 Scene scene = grp.Scene;
2506 if (scene == null)
2507 return null;
2508
2509 int x = (int)targetPosition.X + (int)scene.RegionInfo.WorldLocX;
2510 if (targetPosition.X >= 0)
2511 x++;
2512 else
2513 x--;
2514
2515 int y = (int)targetPosition.Y + (int)scene.RegionInfo.WorldLocY;
2516 if (targetPosition.Y >= 0)
2517 y++;
2518 else
2519 y--;
2520
2521 GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID,x,y);
2522 if (neighbourRegion == null)
2402 { 2523 {
2403 handles.Add(reg.RegionHandle); 2524 return null;
2404 } 2525 }
2405 return handles;
2406 }
2407 2526
2408// private void Dump(string msg, List<ulong> handles) 2527 float newRegionSizeX = neighbourRegion.RegionSizeX;
2409// { 2528 float newRegionSizeY = neighbourRegion.RegionSizeY;
2410// m_log.InfoFormat("-------------- HANDLE DUMP ({0}) ---------", msg); 2529 if (newRegionSizeX == 0)
2411// foreach (ulong handle in handles) 2530 newRegionSizeX = Constants.RegionSize;
2412// { 2531 if (newRegionSizeY == 0)
2413// uint x, y; 2532 newRegionSizeY = Constants.RegionSize;
2414// Utils.LongToUInts(handle, out x, out y);
2415// x = x / Constants.RegionSize;
2416// y = y / Constants.RegionSize;
2417// m_log.InfoFormat("({0}, {1})", x, y);
2418// }
2419// }
2420 2533
2421 #endregion
2422 2534
2423 #region Agent Arrived 2535 newpos.X = targetPosition.X - (neighbourRegion.RegionLocX - (int)scene.RegionInfo.WorldLocX);
2536 newpos.Y = targetPosition.Y - (neighbourRegion.RegionLocY - (int)scene.RegionInfo.WorldLocY);
2424 2537
2425 public void AgentArrivedAtDestination(UUID id)
2426 {
2427 m_entityTransferStateMachine.SetAgentArrivedAtDestination(id);
2428 }
2429 2538
2430 #endregion 2539 const float enterDistance = 0.2f;
2540 newpos.X = Util.Clamp(newpos.X, enterDistance, newRegionSizeX - enterDistance);
2541 newpos.Y = Util.Clamp(newpos.Y, enterDistance, newRegionSizeY - enterDistance);
2431 2542
2432 #region Object Transfers 2543 return neighbourRegion;
2544 }
2433 2545
2546/* not in use. -> CrossPrimGroupIntoNewRegion
2434 /// <summary> 2547 /// <summary>
2435 /// Move the given scene object into a new region depending on which region its absolute position has moved 2548 /// Move the given scene object into a new region depending on which region its absolute position has moved
2436 /// into. 2549 /// into.
@@ -2453,20 +2566,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2453 if (scene == null) 2566 if (scene == null)
2454 return; 2567 return;
2455 2568
2456 if (grp.RootPart.DIE_AT_EDGE)
2457 {
2458 // We remove the object here
2459 try
2460 {
2461 scene.DeleteSceneObject(grp, false);
2462 }
2463 catch (Exception)
2464 {
2465 m_log.Warn("[DATABASE]: exception when trying to remove the prim that crossed the border.");
2466 }
2467 return;
2468 }
2469
2470 // Remember the old group position in case the region lookup fails so position can be restored. 2569 // Remember the old group position in case the region lookup fails so position can be restored.
2471 Vector3 oldGroupPosition = grp.RootPart.GroupPosition; 2570 Vector3 oldGroupPosition = grp.RootPart.GroupPosition;
2472 2571
@@ -2509,7 +2608,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2509 grp.ScheduleGroupForFullUpdate(); 2608 grp.ScheduleGroupForFullUpdate();
2510 } 2609 }
2511 } 2610 }
2512 2611*/
2513 /// <summary> 2612 /// <summary>
2514 /// Move the given scene object into a new region 2613 /// Move the given scene object into a new region
2515 /// </summary> 2614 /// </summary>
@@ -2519,7 +2618,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2519 /// true if the crossing itself was successful, false on failure 2618 /// true if the crossing itself was successful, false on failure
2520 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region 2619 /// FIMXE: we still return true if the crossing object was not successfully deleted from the originating region
2521 /// </returns> 2620 /// </returns>
2522 protected bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent) 2621 public bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent, bool removeScripts)
2523 { 2622 {
2524 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<"); 2623 //m_log.Debug(" >>> CrossPrimGroupIntoNewRegion <<<");
2525 2624
@@ -2551,7 +2650,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2551 // We remove the object here 2650 // We remove the object here
2552 try 2651 try
2553 { 2652 {
2554 grp.Scene.DeleteSceneObject(grp, silent); 2653 grp.Scene.DeleteSceneObject(grp, silent, removeScripts);
2555 } 2654 }
2556 catch (Exception e) 2655 catch (Exception e)
2557 { 2656 {
@@ -2560,30 +2659,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2560 grp, e); 2659 grp, e);
2561 } 2660 }
2562 } 2661 }
2563/*
2564 * done on caller ( not in attachments crossing for now)
2565 else
2566 {
2567
2568 if (!grp.IsDeleted)
2569 {
2570 PhysicsActor pa = grp.RootPart.PhysActor;
2571 if (pa != null)
2572 {
2573 pa.CrossingFailure();
2574 if (grp.RootPart.KeyframeMotion != null)
2575 {
2576 // moved to KeyframeMotion.CrossingFailure
2577// grp.RootPart.Velocity = Vector3.Zero;
2578 grp.RootPart.KeyframeMotion.CrossingFailure();
2579// grp.SendGroupRootTerseUpdate();
2580 }
2581 }
2582 }
2583
2584 m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp);
2585 }
2586 */
2587 } 2662 }
2588 else 2663 else
2589 { 2664 {
@@ -2625,7 +2700,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
2625 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}", 2700 "[ENTITY TRANSFER MODULE]: Sending attachment {0} to region {1}",
2626 clone.UUID, destination.RegionName); 2701 clone.UUID, destination.RegionName);
2627 2702
2628 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent); 2703 CrossPrimGroupIntoNewRegion(destination, Vector3.Zero, clone, silent,true);
2629 } 2704 }
2630 } 2705 }
2631 2706
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
index a3109e0..e3c6c0d 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferStateMachine.cs
@@ -299,7 +299,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
299 id, m_mod.Scene.RegionInfo.RegionName, currentState)); 299 id, m_mod.Scene.RegionInfo.RegionName, currentState));
300 } 300 }
301 301
302 int count = 200; 302 int count = 400;
303 303
304 // There should be no race condition here since no other code should be removing the agent transfer or 304 // There should be no race condition here since no other code should be removing the agent transfer or
305 // changing the state to another other than Transferring => ReceivedAtDestination. 305 // changing the state to another other than Transferring => ReceivedAtDestination.
@@ -354,4 +354,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
354 } 354 }
355 } 355 }
356 } 356 }
357} \ No newline at end of file 357}
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index fa23590..1783e0a 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -239,13 +239,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
239 return region; 239 return region;
240 } 240 }
241 241
242 protected override bool NeedsClosing(float drawdist, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, GridRegion reg) 242 protected override bool NeedsClosing(GridRegion reg, bool OutViewRange)
243 { 243 {
244 if (base.NeedsClosing(drawdist, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 244 if (OutViewRange)
245 return true; 245 return true;
246 246
247 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 247 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
248 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 248 if (flags == -1 || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
249 return true; 249 return true;
250 250
251 return false; 251 return false;
@@ -263,7 +263,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
263 } 263 }
264 } 264 }
265 265
266 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) 266 protected override bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
267 { 267 {
268 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI); 268 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: CreateAgent {0} {1}", reg.ServerURI, finalDestination.ServerURI);
269 reason = string.Empty; 269 reason = string.Empty;
@@ -308,7 +308,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
308 } 308 }
309 } 309 }
310 310
311 return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout); 311 return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, ctx, out reason, out logout);
312 }
313
314 public void TriggerTeleportHome(UUID id, IClientAPI client)
315 {
316 TeleportHome(id, client);
312 } 317 }
313 318
314 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) 319 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
@@ -328,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
328 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance"); 333 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance");
329 334
330 // Check wearables 335 // Check wearables
331 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 336 for (int i = 0; i < sp.Appearance.Wearables.Length ; i++)
332 { 337 {
333 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++) 338 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++)
334 { 339 {
@@ -337,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
337 342
338 bool found = false; 343 bool found = false;
339 foreach (AvatarAppearance a in ExportedAppearance) 344 foreach (AvatarAppearance a in ExportedAppearance)
340 if (a.Wearables[i] != null) 345 if (i < a.Wearables.Length && a.Wearables[i] != null)
341 { 346 {
342 found = true; 347 found = true;
343 break; 348 break;
@@ -351,7 +356,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
351 356
352 found = false; 357 found = false;
353 foreach (AvatarAppearance a in ExportedAppearance) 358 foreach (AvatarAppearance a in ExportedAppearance)
354 if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID) 359 if (i < a.Wearables.Length && sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID)
355 { 360 {
356 found = true; 361 found = true;
357 break; 362 break;
@@ -429,10 +434,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
429 // return base.UpdateAgent(reg, finalDestination, agentData, sp); 434 // return base.UpdateAgent(reg, finalDestination, agentData, sp);
430 //} 435 //}
431 436
432 public override void TriggerTeleportHome(UUID id, IClientAPI client)
433 {
434 TeleportHome(id, client);
435 }
436 437
437 public override bool TeleportHome(UUID id, IClientAPI client) 438 public override bool TeleportHome(UUID id, IClientAPI client)
438 { 439 {
@@ -491,9 +492,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
491 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}", 492 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: teleporting user {0} {1} home to {2} via {3}:{4}",
492 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName); 493 aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ServerURI, homeGatekeeper.RegionName);
493 494
494 DoTeleport( 495 DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
495 sp, homeGatekeeper, finalDestination,
496 position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
497 return true; 496 return true;
498 } 497 }
499 498
@@ -760,4 +759,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
760 return region; 759 return region;
761 } 760 }
762 } 761 }
763} \ No newline at end of file 762}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 5a9efb8..e5373c3 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -178,49 +178,55 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
178 sbyte assetType, 178 sbyte assetType,
179 byte wearableType, uint nextOwnerMask, int creationDate) 179 byte wearableType, uint nextOwnerMask, int creationDate)
180 { 180 {
181 m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}", name, folderID); 181 m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}, transactionID {2}", name,
182 folderID, transactionID);
182 183
183 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) 184 if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId))
184 return; 185 return;
185 186
186 if (transactionID == UUID.Zero) 187 InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId);
188 InventoryFolderBase folder = m_Scene.InventoryService.GetFolder(f);
189
190 if (folder == null || folder.Owner != remoteClient.AgentId)
191 return;
192
193 if (transactionID != UUID.Zero)
187 { 194 {
188 ScenePresence presence; 195 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule;
189 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 196 if (agentTransactions != null)
190 { 197 {
191 byte[] data = null; 198 if (agentTransactions.HandleItemCreationFromTransaction(
199 remoteClient, transactionID, folderID, callbackID, description,
200 name, invType, assetType, wearableType, nextOwnerMask))
201 return;
202 }
203 }
192 204
193 if (invType == (sbyte)InventoryType.Landmark && presence != null) 205 ScenePresence presence;
194 { 206 if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence))
195 string suffix = string.Empty, prefix = string.Empty; 207 {
196 string strdata = GenerateLandmark(presence, out prefix, out suffix); 208 byte[] data = null;
197 data = Encoding.ASCII.GetBytes(strdata);
198 name = prefix + name;
199 description += suffix;
200 }
201 209
202 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); 210 if (invType == (sbyte)InventoryType.Landmark && presence != null)
203 m_Scene.AssetService.Store(asset);
204 m_Scene.CreateNewInventoryItem(
205 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
206 name, description, 0, callbackID, asset.FullID, asset.Type, invType, nextOwnerMask, creationDate);
207 }
208 else
209 { 211 {
210 m_log.ErrorFormat( 212 string suffix = string.Empty, prefix = string.Empty;
211 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", 213 string strdata = GenerateLandmark(presence, out prefix, out suffix);
212 remoteClient.AgentId); 214 data = Encoding.ASCII.GetBytes(strdata);
215 name = prefix + name;
216 description += suffix;
213 } 217 }
218
219 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
220 m_Scene.AssetService.Store(asset);
221 m_Scene.CreateNewInventoryItem(
222 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
223 name, description, 0, callbackID, asset.FullID, asset.Type, invType, nextOwnerMask, creationDate);
214 } 224 }
215 else 225 else
216 { 226 {
217 IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule; 227 m_log.ErrorFormat(
218 if (agentTransactions != null) 228 "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem",
219 { 229 remoteClient.AgentId);
220 agentTransactions.HandleItemCreationFromTransaction(
221 remoteClient, transactionID, folderID, callbackID, description,
222 name, invType, assetType, wearableType, nextOwnerMask);
223 }
224 } 230 }
225 } 231 }
226 232
@@ -272,6 +278,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
272 278
273 remoteClient.SendAlertMessage("Script saved"); 279 remoteClient.SendAlertMessage("Script saved");
274 } 280 }
281 else if ((CustomInventoryType)item.InvType == CustomInventoryType.AnimationSet)
282 {
283 AnimationSet animSet = new AnimationSet(data);
284 if (!animSet.Validate(x => {
285 int perms = m_Scene.InventoryService.GetAssetPermissions(remoteClient.AgentId, x);
286 int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
287 if ((perms & required) != required)
288 return false;
289 return true;
290 }))
291 {
292 data = animSet.ToBytes();
293 }
294 }
275 295
276 AssetBase asset = 296 AssetBase asset =
277 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString()); 297 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data, remoteClient.AgentId.ToString());
@@ -379,33 +399,48 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
379 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient, 399 DeRezAction action, UUID folderID, List<SceneObjectGroup> objlist, IClientAPI remoteClient,
380 bool asAttachment) 400 bool asAttachment)
381 { 401 {
382 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 402 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
383// Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 403 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
384 404 Dictionary<UUID, Quaternion> originalRotations = new Dictionary<UUID, Quaternion>();
385 Dictionary<SceneObjectGroup, KeyframeMotion> group2Keyframe = new Dictionary<SceneObjectGroup, KeyframeMotion>(); 405 // this possible is not needed if keyframes are saved
386 406 Dictionary<UUID, KeyframeMotion> originalKeyframes = new Dictionary<UUID, KeyframeMotion>();
407
387 foreach (SceneObjectGroup objectGroup in objlist) 408 foreach (SceneObjectGroup objectGroup in objlist)
388 { 409 {
389 if (objectGroup.RootPart.KeyframeMotion != null) 410 if (objectGroup.RootPart.KeyframeMotion != null)
390 { 411 {
391 objectGroup.RootPart.KeyframeMotion.Pause(); 412 objectGroup.RootPart.KeyframeMotion.Suspend();
392 group2Keyframe.Add(objectGroup, objectGroup.RootPart.KeyframeMotion);
393 objectGroup.RootPart.KeyframeMotion = null;
394 } 413 }
414 objectGroup.RootPart.SetForce(Vector3.Zero);
415 objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false);
395 416
396// Vector3 inventoryStoredPosition = new Vector3 417 originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion;
397// (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) 418 objectGroup.RootPart.KeyframeMotion = null;
398// ? 250 419
399// : objectGroup.AbsolutePosition.X) 420 Vector3 inventoryStoredPosition = objectGroup.AbsolutePosition;
400// , 421 originalPositions[objectGroup.UUID] = inventoryStoredPosition;
401// (objectGroup.AbsolutePosition.Y > (int)Constants.RegionSize) 422 Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
402// ? 250 423 originalRotations[objectGroup.UUID] = inventoryStoredRotation;
403// : objectGroup.AbsolutePosition.Y, 424
404// objectGroup.AbsolutePosition.Z); 425 // Restore attachment data after trip through the sim
405// 426 if (objectGroup.RootPart.AttachPoint > 0)
406// originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 427 {
407// 428 inventoryStoredPosition = objectGroup.RootPart.AttachedPos;
408// objectGroup.AbsolutePosition = inventoryStoredPosition; 429 inventoryStoredRotation = objectGroup.RootPart.AttachRotation;
430 }
431
432 // Trees could be attached and it's been done, but it makes
433 // no sense. State must be preserved because it's the tree type
434 if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree &&
435 objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree)
436 {
437 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
438 if (objectGroup.RootPart.AttachPoint > 0)
439 objectGroup.RootPart.Shape.LastAttachPoint = objectGroup.RootPart.AttachPoint;
440 }
441
442 objectGroup.AbsolutePosition = inventoryStoredPosition;
443 objectGroup.RootPart.RotationOffset = inventoryStoredRotation;
409 444
410 // Make sure all bits but the ones we want are clear 445 // Make sure all bits but the ones we want are clear
411 // on take. 446 // on take.
@@ -433,9 +468,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
433 else 468 else
434 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); 469 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
435 470
436// // Restore the position of each group now that it has been stored to inventory. 471 // Restore the position of each group now that it has been stored to inventory.
437// foreach (SceneObjectGroup objectGroup in objlist) 472 foreach (SceneObjectGroup objectGroup in objlist)
438// objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 473 {
474 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
475 objectGroup.RootPart.RotationOffset = originalRotations[objectGroup.UUID];
476 objectGroup.RootPart.KeyframeMotion = originalKeyframes[objectGroup.UUID];
477 if (objectGroup.RootPart.KeyframeMotion != null)
478 objectGroup.RootPart.KeyframeMotion.Resume();
479 }
439 480
440 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 481 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
441 482
@@ -492,7 +533,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
492 item.Name = asset.Name; 533 item.Name = asset.Name;
493 item.AssetType = asset.Type; 534 item.AssetType = asset.Type;
494 535
495 AddPermissions(item, objlist[0], objlist, remoteClient); 536 //preserve perms on return
537 if(DeRezAction.Return == action)
538 AddPermissions(item, objlist[0], objlist, null);
539 else
540 AddPermissions(item, objlist[0], objlist, remoteClient);
496 541
497 m_Scene.AddInventoryItem(item); 542 m_Scene.AddInventoryItem(item);
498 543
@@ -510,13 +555,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
510 } 555 }
511 } 556 }
512 557
513 // Restore KeyframeMotion
514 foreach (SceneObjectGroup objectGroup in group2Keyframe.Keys)
515 {
516 objectGroup.RootPart.KeyframeMotion = group2Keyframe[objectGroup];
517 objectGroup.RootPart.KeyframeMotion.Start();
518 }
519
520 // This is a hook to do some per-asset post-processing for subclasses that need that 558 // This is a hook to do some per-asset post-processing for subclasses that need that
521 if (remoteClient != null) 559 if (remoteClient != null)
522 ExportAsset(remoteClient.AgentId, asset.FullID); 560 ExportAsset(remoteClient.AgentId, asset.FullID);
@@ -543,15 +581,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
543 { 581 {
544 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; 582 uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7;
545 uint allObjectsNextOwnerPerms = 0x7fffffff; 583 uint allObjectsNextOwnerPerms = 0x7fffffff;
546 uint allObjectsEveryOnePerms = 0x7fffffff;
547 uint allObjectsGroupPerms = 0x7fffffff;
548 584
585 // For the porposes of inventory, an object is modify if the prims
586 // are modify. This allows renaming an object that contains no
587 // mod items.
549 foreach (SceneObjectGroup grp in objsForEffectivePermissions) 588 foreach (SceneObjectGroup grp in objsForEffectivePermissions)
550 { 589 {
551 effectivePerms &= grp.GetEffectivePermissions(); 590 uint groupPerms = grp.GetEffectivePermissions(true);
552 allObjectsNextOwnerPerms &= grp.RootPart.NextOwnerMask; 591 if ((grp.RootPart.BaseMask & (uint)PermissionMask.Modify) != 0)
553 allObjectsEveryOnePerms &= grp.RootPart.EveryoneMask; 592 groupPerms |= (uint)PermissionMask.Modify;
554 allObjectsGroupPerms &= grp.RootPart.GroupMask; 593
594 effectivePerms &= groupPerms;
555 } 595 }
556 effectivePerms |= (uint)PermissionMask.Move; 596 effectivePerms |= (uint)PermissionMask.Move;
557 597
@@ -565,11 +605,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
565 uint perms = effectivePerms; 605 uint perms = effectivePerms;
566 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms); 606 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms);
567 607
568 item.BasePermissions = perms & allObjectsNextOwnerPerms; 608 item.BasePermissions = perms & so.RootPart.NextOwnerMask;
569 item.CurrentPermissions = item.BasePermissions; 609 item.CurrentPermissions = item.BasePermissions;
570 item.NextPermissions = perms & allObjectsNextOwnerPerms; 610 item.NextPermissions = perms & so.RootPart.NextOwnerMask;
571 item.EveryOnePermissions = allObjectsEveryOnePerms & allObjectsNextOwnerPerms; 611 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask;
572 item.GroupPermissions = allObjectsGroupPerms & allObjectsNextOwnerPerms; 612 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask;
573 613
574 // apply next owner perms on rez 614 // apply next owner perms on rez
575 item.CurrentPermissions |= SceneObjectGroup.SLAM; 615 item.CurrentPermissions |= SceneObjectGroup.SLAM;
@@ -585,9 +625,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
585 625
586 item.BasePermissions = effectivePerms; 626 item.BasePermissions = effectivePerms;
587 item.CurrentPermissions = effectivePerms; 627 item.CurrentPermissions = effectivePerms;
588 item.NextPermissions = allObjectsNextOwnerPerms & effectivePerms; 628 item.NextPermissions = so.RootPart.NextOwnerMask & effectivePerms;
589 item.EveryOnePermissions = allObjectsEveryOnePerms & effectivePerms; 629 item.EveryOnePermissions = so.RootPart.EveryoneMask & effectivePerms;
590 item.GroupPermissions = allObjectsGroupPerms & effectivePerms; 630 item.GroupPermissions = so.RootPart.GroupMask & effectivePerms;
591 631
592 item.CurrentPermissions &= 632 item.CurrentPermissions &=
593 ((uint)PermissionMask.Copy | 633 ((uint)PermissionMask.Copy |
@@ -743,7 +783,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
743 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId) 783 if (so.FromFolderID != UUID.Zero && so.RootPart.OwnerID == remoteClient.AgentId)
744 { 784 {
745 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); 785 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
746 folder = m_Scene.InventoryService.GetFolder(f); 786 if (f != null)
787 folder = m_Scene.InventoryService.GetFolder(f);
747 788
748 if(folder.Type == 14 || folder.Type == 16) 789 if(folder.Type == 14 || folder.Type == 16)
749 { 790 {
@@ -779,16 +820,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
779 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 820 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
780 { 821 {
781// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID); 822// m_log.DebugFormat("[INVENTORY ACCESS MODULE]: RezObject for {0}, item {1}", remoteClient.Name, itemID);
782
783 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 823 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
784 item = m_Scene.InventoryService.GetItem(item); 824 item = m_Scene.InventoryService.GetItem(item);
785 825
786 if (item == null) 826 if (item == null)
787 { 827 {
788 m_log.WarnFormat(
789 "[INVENTORY ACCESS MODULE]: Could not find item {0} for {1} in RezObject()",
790 itemID, remoteClient.Name);
791
792 return null; 828 return null;
793 } 829 }
794 830
@@ -856,12 +892,35 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
856 pos -= bbox / 2; 892 pos -= bbox / 2;
857 } 893 }
858 894
895 int primcount = 0;
896 foreach (SceneObjectGroup g in objlist)
897 primcount += g.PrimCount;
898
899 if (!m_Scene.Permissions.CanRezObject(
900 primcount, remoteClient.AgentId, pos)
901 && !attachment)
902 {
903 // The client operates in no fail mode. It will
904 // have already removed the item from the folder
905 // if it's no copy.
906 // Put it back if it's not an attachment
907 //
908 if (item != null)
909 {
910 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
911 remoteClient.SendBulkUpdateInventory(item);
912 }
913
914 return null;
915 }
916
859 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment)) 917 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
860 return null; 918 return null;
861 919
862 for (int i = 0; i < objlist.Count; i++) 920 for (int i = 0; i < objlist.Count; i++)
863 { 921 {
864 group = objlist[i]; 922 group = objlist[i];
923 SceneObjectPart rootPart = group.RootPart;
865 924
866// m_log.DebugFormat( 925// m_log.DebugFormat(
867// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", 926// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}",
@@ -909,7 +968,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
909 968
910 if (attachment) 969 if (attachment)
911 { 970 {
912 group.RootPart.Flags |= PrimFlags.Phantom; 971// group.RootPart.Flags |= PrimFlags.Phantom;
913 group.IsAttachment = true; 972 group.IsAttachment = true;
914 } 973 }
915 974
@@ -919,7 +978,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
919 // one full update during the attachment 978 // one full update during the attachment
920 // process causes some clients to fail to display the 979 // process causes some clients to fail to display the
921 // attachment properly. 980 // attachment properly.
922 m_Scene.AddNewSceneObject(group, !attachment, false); 981 m_Scene.AddNewSceneObject(group, true, false);
923 982
924 // if attachment we set it's asset id so object updates 983 // if attachment we set it's asset id so object updates
925 // can reflect that, if not, we set it's position in world. 984 // can reflect that, if not, we set it's position in world.
@@ -934,8 +993,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
934 993
935 if (!attachment) 994 if (!attachment)
936 { 995 {
937 SceneObjectPart rootPart = group.RootPart;
938
939 if (rootPart.Shape.PCode == (byte)PCode.Prim) 996 if (rootPart.Shape.PCode == (byte)PCode.Prim)
940 group.ClearPartAttachmentData(); 997 group.ClearPartAttachmentData();
941 998
@@ -953,6 +1010,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
953// remoteClient.Name); 1010// remoteClient.Name);
954 } 1011 }
955 1012
1013 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
1014
956 if (item != null) 1015 if (item != null)
957 DoPostRezWhenFromItem(item, attachment); 1016 DoPostRezWhenFromItem(item, attachment);
958 1017
@@ -1033,10 +1092,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1033 // object itself before we rez. 1092 // object itself before we rez.
1034 // 1093 //
1035 // Only do these for the first object if we are rezzing a coalescence. 1094 // Only do these for the first object if we are rezzing a coalescence.
1036 if (i == 0) 1095 // nahh dont mess with coalescence objects,
1096 // the name in inventory can be change for inventory purpuses only
1097 if (objlist.Count == 1)
1037 { 1098 {
1038 rootPart.Name = item.Name; 1099 rootPart.Name = item.Name;
1039 rootPart.Description = item.Description; 1100 rootPart.Description = item.Description;
1101 }
1102
1103 if ((item.Flags & (uint)InventoryItemFlags.ObjectSlamSale) != 0)
1104 {
1040 rootPart.ObjectSaleType = item.SaleType; 1105 rootPart.ObjectSaleType = item.SaleType;
1041 rootPart.SalePrice = item.SalePrice; 1106 rootPart.SalePrice = item.SalePrice;
1042 } 1107 }
@@ -1047,17 +1112,55 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1047// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", 1112// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}",
1048// rootPart.OwnerID, item.Owner, item.CurrentPermissions); 1113// rootPart.OwnerID, item.Owner, item.CurrentPermissions);
1049 1114
1050 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) 1115 if ((rootPart.OwnerID != item.Owner) ||
1116 (item.CurrentPermissions & 16) != 0 ||
1117 (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
1051 { 1118 {
1052 //Need to kill the for sale here 1119 //Need to kill the for sale here
1053 rootPart.ObjectSaleType = 0; 1120 rootPart.ObjectSaleType = 0;
1054 rootPart.SalePrice = 10; 1121 rootPart.SalePrice = 10;
1055 } 1122
1123 if (m_Scene.Permissions.PropagatePermissions())
1124 {
1125 foreach (SceneObjectPart part in so.Parts)
1126 {
1127 part.GroupMask = 0; // DO NOT propagate here
1056 1128
1057 foreach (SceneObjectPart part in so.Parts) 1129 part.LastOwnerID = part.OwnerID;
1130 part.OwnerID = item.Owner;
1131 part.Inventory.ChangeInventoryOwner(item.Owner);
1132 }
1133
1134 so.ApplyNextOwnerPermissions();
1135
1136 // In case the user has changed flags on a received item
1137 // we have to apply those changes after the slam. Else we
1138 // get a net loss of permissions
1139 foreach (SceneObjectPart part in so.Parts)
1140 {
1141 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
1142 {
1143 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
1144 part.EveryoneMask = item.EveryOnePermissions & part.BaseMask;
1145 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
1146 part.NextOwnerMask = item.NextPermissions & part.BaseMask;
1147 }
1148 }
1149 }
1150 }
1151 else
1058 { 1152 {
1059 part.FromUserInventoryItemID = fromUserInventoryItemId; 1153 foreach (SceneObjectPart part in so.Parts)
1060 part.ApplyPermissionsOnRez(item, true, m_Scene); 1154 {
1155 part.FromUserInventoryItemID = fromUserInventoryItemId;
1156
1157 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
1158 part.EveryoneMask = item.EveryOnePermissions;
1159 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
1160 part.NextOwnerMask = item.NextPermissions;
1161 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
1162 part.GroupMask = item.GroupPermissions;
1163 }
1061 } 1164 }
1062 1165
1063 rootPart.TrimPermissions(); 1166 rootPart.TrimPermissions();
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index 64feec1..93a7cf2 100644
--- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
@@ -205,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
205 m_scene, 205 m_scene,
206 "ScriptEventsPerSecondMonitor", 206 "ScriptEventsPerSecondMonitor",
207 "Script Events", 207 "Script Events",
208 m => m.Scene.StatsReporter.LastReportedSimStats[20], 208 m => m.Scene.StatsReporter.LastReportedSimStats[23],
209 m => string.Format("{0} per second", m.GetValue()))); 209 m => string.Format("{0} per second", m.GetValue())));
210 210
211 m_staticMonitors.Add( 211 m_staticMonitors.Add(
@@ -301,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
301 m_scene, 301 m_scene,
302 "SpareFrameTimeMonitor", 302 "SpareFrameTimeMonitor",
303 "Spare Frame Time", 303 "Spare Frame Time",
304 m => m.Scene.StatsReporter.LastReportedSimStats[21], 304 m => m.Scene.StatsReporter.LastReportedSimStats[38],
305 m => string.Format("{0} ms", m.GetValue()))); 305 m => string.Format("{0} ms", m.GetValue())));
306 306
307 m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); 307 m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 7ecbd26..7d0c47f 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -336,6 +336,102 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
336 } 336 }
337 } 337 }
338 338
339 /// <summary>
340 ///
341 /// </summary>
342 /// <param name="uuid"></param>
343 /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
344 /// <returns></returns>
345 private bool TryGetUserNames(UUID uuid, string[] names)
346 {
347 if (names == null)
348 names = new string[2];
349
350 if (TryGetUserNamesFromCache(uuid, names))
351 return true;
352
353 if (TryGetUserNamesFromServices(uuid, names))
354 return true;
355
356 return false;
357 }
358
359 private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
360 {
361 lock (m_UserCache)
362 {
363 if (m_UserCache.ContainsKey(uuid))
364 {
365 names[0] = m_UserCache[uuid].FirstName;
366 names[1] = m_UserCache[uuid].LastName;
367
368 return true;
369 }
370 }
371
372 return false;
373 }
374
375 /// <summary>
376 /// Try to get the names bound to the given uuid, from the services.
377 /// </summary>
378 /// <returns>True if the name was found, false if not.</returns>
379 /// <param name='uuid'></param>
380 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
381 private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
382 {
383 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
384
385 if (account != null)
386 {
387 names[0] = account.FirstName;
388 names[1] = account.LastName;
389
390 UserData user = new UserData();
391 user.FirstName = account.FirstName;
392 user.LastName = account.LastName;
393
394 lock (m_UserCache)
395 m_UserCache[uuid] = user;
396
397 return true;
398 }
399 else
400 {
401 // Let's try the GridUser service
402 GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
403 if (uInfo != null)
404 {
405 string url, first, last, tmp;
406 UUID u;
407 if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
408 {
409 AddUser(uuid, first, last, url);
410
411 if (m_UserCache.ContainsKey(uuid))
412 {
413 names[0] = m_UserCache[uuid].FirstName;
414 names[1] = m_UserCache[uuid].LastName;
415
416 return true;
417 }
418 }
419 else
420 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
421 }
422// else
423// {
424// m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid);
425// }
426
427 names[0] = "Unknown";
428 names[1] = "UserUMMTGUN9";
429
430 return false;
431 }
432 }
433
434
339 #region IUserManagement 435 #region IUserManagement
340 436
341 public UUID GetUserIdByName(string name) 437 public UUID GetUserIdByName(string name)
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index ea5b34e..a5c7543 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -138,9 +138,9 @@ namespace OpenSim.Region.CoreModules.Hypergrid
138 } 138 }
139 } 139 }
140 140
141 protected override List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 141 protected override List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
142 { 142 {
143 List<MapBlockData> mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); 143 List<MapBlockData> mapBlocks = base.GetAndSendBlocksInternal(remoteClient, minX, minY, maxX, maxY, flag);
144 lock (m_SeenMapBlocks) 144 lock (m_SeenMapBlocks)
145 { 145 {
146 if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) 146 if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId))
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 9dfeb96..87f4798 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -28,15 +28,12 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Linq;
32using System.Net; 31using System.Net;
33using System.Net.Mail; 32using System.Net.Mail;
34using System.Net.Security; 33using System.Net.Security;
35using System.Reflection;
36using System.Text; 34using System.Text;
37using System.Threading; 35using System.Threading;
38using System.Security.Cryptography.X509Certificates; 36using System.Security.Cryptography.X509Certificates;
39using log4net;
40using Nini.Config; 37using Nini.Config;
41using OpenMetaverse; 38using OpenMetaverse;
42using OpenSim.Framework; 39using OpenSim.Framework;
@@ -45,6 +42,7 @@ using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
47using Mono.Addins; 44using Mono.Addins;
45using Amib.Threading;
48 46
49/***************************************************** 47/*****************************************************
50 * 48 *
@@ -108,6 +106,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
108 private Dictionary<UUID, HttpRequestClass> m_pendingRequests; 106 private Dictionary<UUID, HttpRequestClass> m_pendingRequests;
109 private Scene m_scene; 107 private Scene m_scene;
110 // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); 108 // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>();
109 public static SmartThreadPool ThreadPool = null;
111 110
112 public HttpRequestModule() 111 public HttpRequestModule()
113 { 112 {
@@ -290,29 +289,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
290 return true; 289 return true;
291 } 290 }
292 291
293 public void StopHttpRequestsForScript(UUID id) 292 public void StopHttpRequest(uint m_localID, UUID m_itemID)
294 { 293 {
295 if (m_pendingRequests != null) 294 if (m_pendingRequests != null)
296 { 295 {
297 List<UUID> keysToRemove = null;
298
299 lock (HttpListLock) 296 lock (HttpListLock)
300 { 297 {
301 foreach (HttpRequestClass req in m_pendingRequests.Values) 298 HttpRequestClass tmpReq;
299 if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
302 { 300 {
303 if (req.ItemID == id) 301 tmpReq.Stop();
304 { 302 m_pendingRequests.Remove(m_itemID);
305 req.Stop();
306
307 if (keysToRemove == null)
308 keysToRemove = new List<UUID>();
309
310 keysToRemove.Add(req.ReqID);
311 }
312 } 303 }
313
314 if (keysToRemove != null)
315 keysToRemove.ForEach(keyToRemove => m_pendingRequests.Remove(keyToRemove));
316 } 304 }
317 } 305 }
318 } 306 }
@@ -330,13 +318,19 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
330 { 318 {
331 lock (HttpListLock) 319 lock (HttpListLock)
332 { 320 {
333 foreach (HttpRequestClass req in m_pendingRequests.Values) 321 foreach (UUID luid in m_pendingRequests.Keys)
334 { 322 {
335 if (req.Finished) 323 HttpRequestClass tmpReq;
336 return req; 324
325 if (m_pendingRequests.TryGetValue(luid, out tmpReq))
326 {
327 if (tmpReq.Finished)
328 {
329 return tmpReq;
330 }
331 }
337 } 332 }
338 } 333 }
339
340 return null; 334 return null;
341 } 335 }
342 336
@@ -363,9 +357,32 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
363 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 357 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
364 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 358 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
365 359
360
366 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); 361 m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config);
362 int maxThreads = 15;
363
364 IConfig httpConfig = config.Configs["HttpRequestModule"];
365 if (httpConfig != null)
366 {
367 maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads);
368 }
367 369
368 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 370 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
371
372 // First instance sets this up for all sims
373 if (ThreadPool == null)
374 {
375 STPStartInfo startInfo = new STPStartInfo();
376 startInfo.IdleTimeout = 20000;
377 startInfo.MaxWorkerThreads = maxThreads;
378 startInfo.MinWorkerThreads = 1;
379 startInfo.ThreadPriority = ThreadPriority.BelowNormal;
380 startInfo.StartSuspended = true;
381 startInfo.ThreadPoolName = "ScriptsHttpReq";
382
383 ThreadPool = new SmartThreadPool(startInfo);
384 ThreadPool.Start();
385 }
369 } 386 }
370 387
371 public void AddRegion(Scene scene) 388 public void AddRegion(Scene scene)
@@ -409,8 +426,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
409 426
410 public class HttpRequestClass : IServiceRequest 427 public class HttpRequestClass : IServiceRequest
411 { 428 {
412// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
413
414 // Constants for parameters 429 // Constants for parameters
415 // public const int HTTP_BODY_MAXLENGTH = 2; 430 // public const int HTTP_BODY_MAXLENGTH = 2;
416 // public const int HTTP_METHOD = 0; 431 // public const int HTTP_METHOD = 0;
@@ -437,6 +452,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
437 public string HttpMIMEType = "text/plain;charset=utf-8"; 452 public string HttpMIMEType = "text/plain;charset=utf-8";
438 public int HttpTimeout; 453 public int HttpTimeout;
439 public bool HttpVerifyCert = true; 454 public bool HttpVerifyCert = true;
455 public IWorkItemResult WorkItem = null;
456
440 //public bool HttpVerboseThrottle = true; // not implemented 457 //public bool HttpVerboseThrottle = true; // not implemented
441 public List<string> HttpCustomHeaders = null; 458 public List<string> HttpCustomHeaders = null;
442 public bool HttpPragmaNoCache = true; 459 public bool HttpPragmaNoCache = true;
@@ -484,15 +501,40 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
484 501
485 public void Process() 502 public void Process()
486 { 503 {
504 _finished = false;
505
506 lock (HttpRequestModule.ThreadPool)
507 WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null);
508 }
509
510 private object StpSendWrapper(object o)
511 {
487 SendRequest(); 512 SendRequest();
513 return null;
488 } 514 }
489 515
516 /*
517 * TODO: More work on the response codes. Right now
518 * returning 200 for success or 499 for exception
519 */
520
490 public void SendRequest() 521 public void SendRequest()
491 { 522 {
523 HttpWebResponse response = null;
524 Stream resStream = null;
525 StringBuilder sb = new StringBuilder();
526 byte[] buf = new byte[8192];
527 string tempString = null;
528 int count = 0;
529
492 try 530 try
493 { 531 {
494 Request = (HttpWebRequest)WebRequest.Create(Url); 532 Request = (HttpWebRequest)WebRequest.Create(Url);
495 Request.AllowAutoRedirect = false; 533 Request.AllowAutoRedirect = false;
534
535 //This works around some buggy HTTP Servers like Lighttpd
536 Request.ServicePoint.Expect100Continue = false;
537
496 Request.Method = HttpMethod; 538 Request.Method = HttpMethod;
497 Request.ContentType = HttpMIMEType; 539 Request.ContentType = HttpMIMEType;
498 540
@@ -500,7 +542,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
500 { 542 {
501 // We could hijack Connection Group Name to identify 543 // We could hijack Connection Group Name to identify
502 // a desired security exception. But at the moment we'll use a dummy header instead. 544 // a desired security exception. But at the moment we'll use a dummy header instead.
503// Request.ConnectionGroupName = "NoVerify";
504 Request.Headers.Add("NoVerifyCert", "true"); 545 Request.Headers.Add("NoVerifyCert", "true");
505 } 546 }
506// else 547// else
@@ -533,14 +574,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
533 } 574 }
534 } 575 }
535 576
536 if (ResponseHeaders != null) 577 foreach (KeyValuePair<string, string> entry in ResponseHeaders)
537 { 578 if (entry.Key.ToLower().Equals("user-agent"))
538 foreach (KeyValuePair<string, string> entry in ResponseHeaders) 579 Request.UserAgent = entry.Value;
539 if (entry.Key.ToLower().Equals("user-agent") && Request is HttpWebRequest) 580 else
540 ((HttpWebRequest)Request).UserAgent = entry.Value; 581 Request.Headers[entry.Key] = entry.Value;
541 else
542 Request.Headers[entry.Key] = entry.Value;
543 }
544 582
545 // Encode outbound data 583 // Encode outbound data
546 if (!string.IsNullOrEmpty(OutboundBody)) 584 if (!string.IsNullOrEmpty(OutboundBody))
@@ -552,12 +590,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
552 bstream.Write(data, 0, data.Length); 590 bstream.Write(data, 0, data.Length);
553 } 591 }
554 592
593 Request.Timeout = HttpTimeout;
555 try 594 try
556 { 595 {
557 IAsyncResult result = (IAsyncResult)Request.BeginGetResponse(ResponseCallback, null); 596 // execute the request
558 597 response = (HttpWebResponse) Request.GetResponse();
559 ThreadPool.RegisterWaitForSingleObject(
560 result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), null, HttpTimeout, true);
561 } 598 }
562 catch (WebException e) 599 catch (WebException e)
563 { 600 {
@@ -565,63 +602,72 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
565 { 602 {
566 throw; 603 throw;
567 } 604 }
605 response = (HttpWebResponse)e.Response;
606 }
568 607
569 HttpWebResponse response = (HttpWebResponse)e.Response; 608 Status = (int)response.StatusCode;
570 609
571 Status = (int)response.StatusCode; 610 resStream = response.GetResponseStream();
572 ResponseBody = response.StatusDescription;
573 _finished = true;
574 }
575 }
576 catch (Exception e)
577 {
578// m_log.Debug(
579// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on request to {0} for {1} ", Url, ItemID), e);
580 611
581 Status = (int)OSHttpStatusCode.ClientErrorJoker; 612 do
582 ResponseBody = e.Message; 613 {
583 _finished = true; 614 // fill the buffer with data
584 } 615 count = resStream.Read(buf, 0, buf.Length);
585 }
586 616
587 private void ResponseCallback(IAsyncResult ar) 617 // make sure we read some data
588 { 618 if (count != 0)
589 HttpWebResponse response = null; 619 {
620 // translate from bytes to ASCII text
621 tempString = Util.UTF8.GetString(buf, 0, count);
590 622
591 try 623 // continue building the string
624 sb.Append(tempString);
625 if (sb.Length > 2048)
626 break;
627 }
628 } while (count > 0); // any more data to read?
629
630 ResponseBody = sb.ToString().Replace("\r", "");
631 }
632 catch (WebException e)
592 { 633 {
593 try 634 if (e.Status == WebExceptionStatus.ProtocolError)
594 { 635 {
595 response = (HttpWebResponse)Request.EndGetResponse(ar); 636 HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response;
596 } 637 Status = (int)webRsp.StatusCode;
597 catch (WebException e) 638 try
598 {
599 if (e.Status != WebExceptionStatus.ProtocolError)
600 { 639 {
601 throw; 640 using (Stream responseStream = webRsp.GetResponseStream())
641 {
642 using (StreamReader reader = new StreamReader(responseStream))
643 ResponseBody = reader.ReadToEnd();
644 }
645 }
646 catch
647 {
648 ResponseBody = webRsp.StatusDescription;
602 } 649 }
603 650 }
604 response = (HttpWebResponse)e.Response; 651 else
652 {
653 Status = (int)OSHttpStatusCode.ClientErrorJoker;
654 ResponseBody = e.Message;
605 } 655 }
606 656
607 Status = (int)response.StatusCode; 657 if (ResponseBody == null)
658 ResponseBody = String.Empty;
608 659
609 using (Stream stream = response.GetResponseStream()) 660 _finished = true;
610 { 661 return;
611 StreamReader reader = new StreamReader(stream, Encoding.UTF8);
612 ResponseBody = reader.ReadToEnd();
613 }
614 } 662 }
615 catch (Exception e) 663 catch (Exception e)
616 { 664 {
617 Status = (int)OSHttpStatusCode.ClientErrorJoker; 665 // Don't crash on anything else
618 ResponseBody = e.Message;
619
620// m_log.Debug(
621// string.Format("[SCRIPTS HTTP REQUESTS]: Exception on response to {0} for {1} ", Url, ItemID), e);
622 } 666 }
623 finally 667 finally
624 { 668 {
669 if (resStream != null)
670 resStream.Close();
625 if (response != null) 671 if (response != null)
626 response.Close(); 672 response.Close();
627 673
@@ -672,20 +718,25 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
672 _finished = true; 718 _finished = true;
673 } 719 }
674 } 720 }
675 }
676 721
677 private void TimeoutCallback(object state, bool timedOut) 722 if (ResponseBody == null)
678 { 723 ResponseBody = String.Empty;
679 if (timedOut) 724
680 Request.Abort(); 725 _finished = true;
681 } 726 }
682 727
683 public void Stop() 728 public void Stop()
684 { 729 {
685// m_log.DebugFormat("[SCRIPTS HTTP REQUESTS]: Stopping request to {0} for {1} ", Url, ItemID); 730 try
686 731 {
687 if (Request != null) 732 if (!WorkItem.Cancel())
688 Request.Abort(); 733 {
734 WorkItem.Cancel(true);
735 }
736 }
737 catch (Exception)
738 {
739 }
689 } 740 }
690 } 741 }
691} \ No newline at end of file 742}
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 99a3122..a21931c 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -42,40 +42,16 @@ using OpenSim.Region.Framework.Scenes;
42 42
43namespace OpenSim.Region.CoreModules.Scripting.LSLHttp 43namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
44{ 44{
45 /// <summary>
46 /// Data describing an external URL set up by a script.
47 /// </summary>
48 public class UrlData 45 public class UrlData
49 { 46 {
50 /// <summary>
51 /// Scene object part hosting the script
52 /// </summary>
53 public UUID hostID; 47 public UUID hostID;
54
55 /// <summary>
56 /// The item ID of the script that requested the URL.
57 /// </summary>
58 public UUID itemID; 48 public UUID itemID;
59
60 /// <summary>
61 /// The script engine that runs the script.
62 /// </summary>
63 public IScriptModule engine; 49 public IScriptModule engine;
64
65 /// <summary>
66 /// The generated URL.
67 /// </summary>
68 public string url; 50 public string url;
69
70 /// <summary>
71 /// The random UUID component of the generated URL.
72 /// </summary>
73 public UUID urlcode; 51 public UUID urlcode;
74
75 /// <summary>
76 /// The external requests currently being processed or awaiting retrieval for this URL.
77 /// </summary>
78 public Dictionary<UUID, RequestData> requests; 52 public Dictionary<UUID, RequestData> requests;
53 public bool isSsl;
54 public Scene scene;
79 } 55 }
80 56
81 public class RequestData 57 public class RequestData
@@ -89,7 +65,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
89 //public ManualResetEvent ev; 65 //public ManualResetEvent ev;
90 public bool requestDone; 66 public bool requestDone;
91 public int startTime; 67 public int startTime;
68 public bool responseSent;
92 public string uri; 69 public string uri;
70 public bool allowResponseType = false;
71 public UUID hostID;
72 public Scene scene;
93 } 73 }
94 74
95 /// <summary> 75 /// <summary>
@@ -102,20 +82,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
102 LogManager.GetLogger( 82 LogManager.GetLogger(
103 MethodBase.GetCurrentMethod().DeclaringType); 83 MethodBase.GetCurrentMethod().DeclaringType);
104 84
105 /// <summary> 85 private Dictionary<UUID, UrlData> m_RequestMap =
106 /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID 86 new Dictionary<UUID, UrlData>();
107 /// randomly generated when a request is received for this URL.
108 /// </summary>
109 /// <remarks>
110 /// Manipulation or retrieval from this dictionary must be locked on m_UrlMap to preserve consistency with
111 /// m_UrlMap
112 /// </remarks>
113 private Dictionary<UUID, UrlData> m_RequestMap = new Dictionary<UUID, UrlData>();
114 87
115 /// <summary> 88 private Dictionary<string, UrlData> m_UrlMap =
116 /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL 89 new Dictionary<string, UrlData>();
117 /// </summary>
118 private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>();
119 90
120 private uint m_HttpsPort = 0; 91 private uint m_HttpsPort = 0;
121 private IHttpServer m_HttpServer = null; 92 private IHttpServer m_HttpServer = null;
@@ -126,7 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
126 /// <summary> 97 /// <summary>
127 /// The default maximum number of urls 98 /// The default maximum number of urls
128 /// </summary> 99 /// </summary>
129 public const int DefaultTotalUrls = 100; 100 public const int DefaultTotalUrls = 15000;
130 101
131 /// <summary> 102 /// <summary>
132 /// Maximum number of external urls that can be set up by this module. 103 /// Maximum number of external urls that can be set up by this module.
@@ -204,6 +175,17 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
204 175
205 public void RemoveRegion(Scene scene) 176 public void RemoveRegion(Scene scene)
206 { 177 {
178 // Drop references to that scene
179 foreach (KeyValuePair<string, UrlData> kvp in m_UrlMap)
180 {
181 if (kvp.Value.scene == scene)
182 kvp.Value.scene = null;
183 }
184 foreach (KeyValuePair<UUID, UrlData> kvp in m_RequestMap)
185 {
186 if (kvp.Value.scene == scene)
187 kvp.Value.scene = null;
188 }
207 } 189 }
208 190
209 public void Close() 191 public void Close()
@@ -229,8 +211,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
229 urlData.engine = engine; 211 urlData.engine = engine;
230 urlData.url = url; 212 urlData.url = url;
231 urlData.urlcode = urlcode; 213 urlData.urlcode = urlcode;
214 urlData.isSsl = false;
232 urlData.requests = new Dictionary<UUID, RequestData>(); 215 urlData.requests = new Dictionary<UUID, RequestData>();
233 216 urlData.scene = host.ParentGroup.Scene;
217
234 m_UrlMap[url] = urlData; 218 m_UrlMap[url] = urlData;
235 219
236 string uri = "/lslhttp/" + urlcode.ToString() + "/"; 220 string uri = "/lslhttp/" + urlcode.ToString() + "/";
@@ -240,9 +224,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
240 args.Type = PollServiceEventArgs.EventType.LslHttp; 224 args.Type = PollServiceEventArgs.EventType.LslHttp;
241 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 225 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
242 226
243 m_log.DebugFormat( 227// m_log.DebugFormat(
244 "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", 228// "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}",
245 uri, itemID, host.Name, host.LocalId); 229// uri, itemID, host.Name, host.LocalId);
246 230
247 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 231 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
248 } 232 }
@@ -275,8 +259,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
275 urlData.engine = engine; 259 urlData.engine = engine;
276 urlData.url = url; 260 urlData.url = url;
277 urlData.urlcode = urlcode; 261 urlData.urlcode = urlcode;
262 urlData.isSsl = true;
278 urlData.requests = new Dictionary<UUID, RequestData>(); 263 urlData.requests = new Dictionary<UUID, RequestData>();
279 264
265
280 m_UrlMap[url] = urlData; 266 m_UrlMap[url] = urlData;
281 267
282 string uri = "/lslhttps/" + urlcode.ToString() + "/"; 268 string uri = "/lslhttps/" + urlcode.ToString() + "/";
@@ -286,9 +272,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
286 args.Type = PollServiceEventArgs.EventType.LslHttp; 272 args.Type = PollServiceEventArgs.EventType.LslHttp;
287 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 273 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
288 274
289 m_log.DebugFormat( 275// m_log.DebugFormat(
290 "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}", 276// "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}",
291 uri, itemID, host.Name, host.LocalId); 277// uri, itemID, host.Name, host.LocalId);
292 278
293 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url }); 279 engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
294 } 280 }
@@ -307,12 +293,15 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
307 return; 293 return;
308 } 294 }
309 295
310 foreach (UUID req in data.requests.Keys) 296 lock (m_RequestMap)
311 m_RequestMap.Remove(req); 297 {
312 298 foreach (UUID req in data.requests.Keys)
313 m_log.DebugFormat( 299 m_RequestMap.Remove(req);
314 "[URL MODULE]: Releasing url {0} for {1} in {2}", 300 }
315 url, data.itemID, data.hostID); 301
302// m_log.DebugFormat(
303// "[URL MODULE]: Releasing url {0} for {1} in {2}",
304// url, data.itemID, data.hostID);
316 305
317 RemoveUrl(data); 306 RemoveUrl(data);
318 m_UrlMap.Remove(url); 307 m_UrlMap.Remove(url);
@@ -337,29 +326,39 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
337 326
338 public void HttpResponse(UUID request, int status, string body) 327 public void HttpResponse(UUID request, int status, string body)
339 { 328 {
340 lock (m_UrlMap) 329 lock (m_RequestMap)
341 { 330 {
342 if (m_RequestMap.ContainsKey(request)) 331 if (m_RequestMap.ContainsKey(request))
343 { 332 {
344 UrlData urlData = m_RequestMap[request]; 333 UrlData urlData = m_RequestMap[request];
345 string responseBody = body; 334 if (!urlData.requests[request].responseSent)
346 if (urlData.requests[request].responseType.Equals("text/plain"))
347 { 335 {
348 string value; 336 string responseBody = body;
349 if (urlData.requests[request].headers.TryGetValue("user-agent", out value)) 337
338 // If we have no OpenID from built-in browser, disable this
339 if (!urlData.requests[request].allowResponseType)
340 urlData.requests[request].responseType = "text/plain";
341
342 if (urlData.requests[request].responseType.Equals("text/plain"))
350 { 343 {
351 if (value != null && value.IndexOf("MSIE") >= 0) 344 string value;
345 if (urlData.requests[request].headers.TryGetValue("user-agent", out value))
352 { 346 {
353 // wrap the html escaped response if the target client is IE 347 if (value != null && value.IndexOf("MSIE") >= 0)
354 // It ignores "text/plain" if the body is html 348 {
355 responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>"; 349 // wrap the html escaped response if the target client is IE
350 // It ignores "text/plain" if the body is html
351 responseBody = "<html>" + System.Web.HttpUtility.HtmlEncode(body) + "</html>";
352 }
356 } 353 }
357 } 354 }
355
356 urlData.requests[request].responseCode = status;
357 urlData.requests[request].responseBody = body;
358 //urlData.requests[request].ev.Set();
359 urlData.requests[request].requestDone = true;
360 urlData.requests[request].responseSent = true;
358 } 361 }
359 urlData.requests[request].responseCode = status;
360 urlData.requests[request].responseBody = responseBody;
361 //urlData.requests[request].ev.Set();
362 urlData.requests[request].requestDone =true;
363 } 362 }
364 else 363 else
365 { 364 {
@@ -370,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
370 369
371 public string GetHttpHeader(UUID requestId, string header) 370 public string GetHttpHeader(UUID requestId, string header)
372 { 371 {
373 lock (m_UrlMap) 372 lock (m_RequestMap)
374 { 373 {
375 if (m_RequestMap.ContainsKey(requestId)) 374 if (m_RequestMap.ContainsKey(requestId))
376 { 375 {
@@ -384,7 +383,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
384 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId); 383 m_log.Warn("[HttpRequestHandler] There was no http-in request with id " + requestId);
385 } 384 }
386 } 385 }
387
388 return String.Empty; 386 return String.Empty;
389 } 387 }
390 388
@@ -408,8 +406,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
408 { 406 {
409 RemoveUrl(url.Value); 407 RemoveUrl(url.Value);
410 removeURLs.Add(url.Key); 408 removeURLs.Add(url.Key);
411 foreach (UUID req in url.Value.requests.Keys) 409 lock (m_RequestMap)
412 m_RequestMap.Remove(req); 410 {
411 foreach (UUID req in url.Value.requests.Keys)
412 m_RequestMap.Remove(req);
413 }
413 } 414 }
414 } 415 }
415 416
@@ -430,9 +431,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
430 { 431 {
431 RemoveUrl(url.Value); 432 RemoveUrl(url.Value);
432 removeURLs.Add(url.Key); 433 removeURLs.Add(url.Key);
433 434 lock (m_RequestMap)
434 foreach (UUID req in url.Value.requests.Keys) 435 {
435 m_RequestMap.Remove(req); 436 foreach (UUID req in url.Value.requests.Keys)
437 m_RequestMap.Remove(req);
438 }
436 } 439 }
437 } 440 }
438 441
@@ -441,123 +444,128 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
441 } 444 }
442 } 445 }
443 446
447
444 private void RemoveUrl(UrlData data) 448 private void RemoveUrl(UrlData data)
445 { 449 {
446 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/" + data.urlcode.ToString() + "/"); 450 if (data.isSsl)
451 m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/");
452 else
453 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
447 } 454 }
448 455
449 private Hashtable NoEvents(UUID requestID, UUID sessionID) 456 private Hashtable NoEvents(UUID requestID, UUID sessionID)
450 { 457 {
451 Hashtable response = new Hashtable(); 458 Hashtable response = new Hashtable();
452 UrlData urlData; 459 UrlData url;
453 460 int startTime = 0;
454 lock (m_UrlMap) 461 lock (m_RequestMap)
455 { 462 {
456 // We need to return a 404 here in case the request URL was removed at exactly the same time that a
457 // request was made. In this case, the request thread can outrace llRemoveURL() and still be polling
458 // for the request ID.
459 if (!m_RequestMap.ContainsKey(requestID)) 463 if (!m_RequestMap.ContainsKey(requestID))
460 {
461 response["int_response_code"] = 404;
462 response["str_response_string"] = "";
463 response["keepalive"] = false;
464 response["reusecontext"] = false;
465
466 return response; 464 return response;
467 } 465 url = m_RequestMap[requestID];
466 startTime = url.requests[requestID].startTime;
467 }
468 468
469 urlData = m_RequestMap[requestID]; 469 if (System.Environment.TickCount - startTime > 25000)
470 {
471 response["int_response_code"] = 500;
472 response["str_response_string"] = "Script timeout";
473 response["content_type"] = "text/plain";
474 response["keepalive"] = false;
475 response["reusecontext"] = false;
470 476
471 if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000) 477 //remove from map
478 lock (url.requests)
479 {
480 url.requests.Remove(requestID);
481 }
482 lock (m_RequestMap)
472 { 483 {
473 response["int_response_code"] = 500;
474 response["str_response_string"] = "Script timeout";
475 response["content_type"] = "text/plain";
476 response["keepalive"] = false;
477 response["reusecontext"] = false;
478
479 //remove from map
480 urlData.requests.Remove(requestID);
481 m_RequestMap.Remove(requestID); 484 m_RequestMap.Remove(requestID);
482
483 return response;
484 } 485 }
486
487 return response;
485 } 488 }
486 489
490
487 return response; 491 return response;
488 } 492 }
489 493
490 private bool HasEvents(UUID requestID, UUID sessionID) 494 private bool HasEvents(UUID requestID, UUID sessionID)
491 { 495 {
492 lock (m_UrlMap) 496 UrlData url=null;
497
498 lock (m_RequestMap)
493 { 499 {
494 // We return true here because an external URL request that happened at the same time as an llRemoveURL()
495 // can still make it through to HttpRequestHandler(). That will return without setting up a request
496 // when it detects that the URL has been removed. The poller, however, will continue to ask for
497 // events for that request, so here we will signal that there are events and in GetEvents we will
498 // return a 404.
499 if (!m_RequestMap.ContainsKey(requestID)) 500 if (!m_RequestMap.ContainsKey(requestID))
500 { 501 {
501 return true; 502 return false;
502 } 503 }
503 504 url = m_RequestMap[requestID];
504 UrlData urlData = m_RequestMap[requestID]; 505 }
505 506 lock (url.requests)
506 if (!urlData.requests.ContainsKey(requestID)) 507 {
508 if (!url.requests.ContainsKey(requestID))
507 { 509 {
508 return true; 510 return false;
509 } 511 }
510 512 else
511 // Trigger return of timeout response.
512 if (System.Environment.TickCount - urlData.requests[requestID].startTime > 25000)
513 { 513 {
514 return true; 514 if (System.Environment.TickCount - url.requests[requestID].startTime > 25000)
515 {
516 return true;
517 }
518 if (url.requests[requestID].requestDone)
519 return true;
520 else
521 return false;
515 } 522 }
516
517 return urlData.requests[requestID].requestDone;
518 } 523 }
519 } 524 }
520
521 private Hashtable GetEvents(UUID requestID, UUID sessionID) 525 private Hashtable GetEvents(UUID requestID, UUID sessionID)
522 { 526 {
523 Hashtable response; 527 UrlData url = null;
528 RequestData requestData = null;
524 529
525 lock (m_UrlMap) 530 lock (m_RequestMap)
526 { 531 {
527 UrlData url = null;
528 RequestData requestData = null;
529
530 if (!m_RequestMap.ContainsKey(requestID)) 532 if (!m_RequestMap.ContainsKey(requestID))
531 return NoEvents(requestID, sessionID); 533 return NoEvents(requestID,sessionID);
532
533 url = m_RequestMap[requestID]; 534 url = m_RequestMap[requestID];
535 }
536 lock (url.requests)
537 {
534 requestData = url.requests[requestID]; 538 requestData = url.requests[requestID];
539 }
540
541 if (!requestData.requestDone)
542 return NoEvents(requestID,sessionID);
543
544 Hashtable response = new Hashtable();
535 545
536 if (!requestData.requestDone) 546 if (System.Environment.TickCount - requestData.startTime > 25000)
537 return NoEvents(requestID, sessionID); 547 {
538 548 response["int_response_code"] = 500;
539 response = new Hashtable(); 549 response["str_response_string"] = "Script timeout";
540 550 response["content_type"] = "text/plain";
541 if (System.Environment.TickCount - requestData.startTime > 25000)
542 {
543 response["int_response_code"] = 500;
544 response["str_response_string"] = "Script timeout";
545 response["content_type"] = "text/plain";
546 response["keepalive"] = false;
547 response["reusecontext"] = false;
548 return response;
549 }
550
551 //put response
552 response["int_response_code"] = requestData.responseCode;
553 response["str_response_string"] = requestData.responseBody;
554 response["content_type"] = requestData.responseType;
555 // response["content_type"] = "text/plain";
556 response["keepalive"] = false; 551 response["keepalive"] = false;
557 response["reusecontext"] = false; 552 response["reusecontext"] = false;
558 553 return response;
559 //remove from map 554 }
555 //put response
556 response["int_response_code"] = requestData.responseCode;
557 response["str_response_string"] = requestData.responseBody;
558 response["content_type"] = requestData.responseType;
559 response["keepalive"] = false;
560 response["reusecontext"] = false;
561
562 //remove from map
563 lock (url.requests)
564 {
560 url.requests.Remove(requestID); 565 url.requests.Remove(requestID);
566 }
567 lock (m_RequestMap)
568 {
561 m_RequestMap.Remove(requestID); 569 m_RequestMap.Remove(requestID);
562 } 570 }
563 571
@@ -566,41 +574,46 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
566 574
567 public void HttpRequestHandler(UUID requestID, Hashtable request) 575 public void HttpRequestHandler(UUID requestID, Hashtable request)
568 { 576 {
569 string uri = request["uri"].ToString(); 577 lock (request)
570 bool is_ssl = uri.Contains("lslhttps");
571
572 try
573 { 578 {
574 Hashtable headers = (Hashtable)request["headers"]; 579 string uri = request["uri"].ToString();
580 bool is_ssl = uri.Contains("lslhttps");
575 581
576// string uri_full = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/"; 582 try
583 {
584 Hashtable headers = (Hashtable)request["headers"];
577 585
578 int pos1 = uri.IndexOf("/");// /lslhttp 586// string uri_full = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri;// "/lslhttp/" + urlcode.ToString() + "/";
579 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
580 int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp/<UUID>/
581 string uri_tmp = uri.Substring(0, pos3 + 1);
582 //HTTP server code doesn't provide us with QueryStrings
583 string pathInfo;
584 string queryString;
585 queryString = "";
586 587
587 pathInfo = uri.Substring(pos3); 588 int pos1 = uri.IndexOf("/");// /lslhttp
589 int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/
590 int pos3 = uri.IndexOf("/", pos2 + 1); // /lslhttp/urlcode
588 591
589 UrlData urlData = null; 592 string uri_tmp = uri.Substring(0, pos3 + 1);
593 //HTTP server code doesn't provide us with QueryStrings
594 string pathInfo;
595 string queryString;
596 queryString = "";
590 597
591 lock (m_UrlMap) 598 pathInfo = uri.Substring(pos3);
592 {
593 string url;
594 599
595 if (is_ssl) 600 UrlData url = null;
596 url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp; 601 string urlkey;
602 if (!is_ssl)
603 urlkey = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp;
604 //m_UrlMap[];
597 else 605 else
598 url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + uri_tmp; 606 urlkey = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + uri_tmp;
599 607
600 // Avoid a race - the request URL may have been released via llRequestUrl() whilst this 608 if (m_UrlMap.ContainsKey(urlkey))
601 // request was being processed. 609 {
602 if (!m_UrlMap.TryGetValue(url, out urlData)) 610 url = m_UrlMap[urlkey];
611 }
612 else
613 {
614 //m_log.Warn("[HttpRequestHandler]: http-in request failed; no such url: "+urlkey.ToString());
603 return; 615 return;
616 }
604 617
605 //for llGetHttpHeader support we need to store original URI here 618 //for llGetHttpHeader support we need to store original URI here
606 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers 619 //to make x-path-info / x-query-string / x-script-url / x-remote-ip headers
@@ -611,6 +624,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
611 requestData.requestDone = false; 624 requestData.requestDone = false;
612 requestData.startTime = System.Environment.TickCount; 625 requestData.startTime = System.Environment.TickCount;
613 requestData.uri = uri; 626 requestData.uri = uri;
627 requestData.hostID = url.hostID;
628 requestData.scene = url.scene;
614 if (requestData.headers == null) 629 if (requestData.headers == null)
615 requestData.headers = new Dictionary<string, string>(); 630 requestData.headers = new Dictionary<string, string>();
616 631
@@ -619,8 +634,33 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
619 string key = (string)header.Key; 634 string key = (string)header.Key;
620 string value = (string)header.Value; 635 string value = (string)header.Value;
621 requestData.headers.Add(key, value); 636 requestData.headers.Add(key, value);
637 if (key == "cookie")
638 {
639 string[] parts = value.Split(new char[] {'='});
640 if (parts[0] == "agni_sl_session_id" && parts.Length > 1)
641 {
642 string cookie = Uri.UnescapeDataString(parts[1]);
643 string[] crumbs = cookie.Split(new char[] {':'});
644 UUID owner;
645 if (crumbs.Length == 2 && UUID.TryParse(crumbs[0], out owner))
646 {
647 if (crumbs[1].Length == 32)
648 {
649 Scene scene = requestData.scene;
650 if (scene != null)
651 {
652 SceneObjectPart host = scene.GetSceneObjectPart(requestData.hostID);
653 if (host != null)
654 {
655 if (host.OwnerID == owner)
656 requestData.allowResponseType = true;
657 }
658 }
659 }
660 }
661 }
662 }
622 } 663 }
623
624 foreach (DictionaryEntry de in request) 664 foreach (DictionaryEntry de in request)
625 { 665 {
626 if (de.Key.ToString() == "querystringkeys") 666 if (de.Key.ToString() == "querystringkeys")
@@ -631,13 +671,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
631 if (request.ContainsKey(key)) 671 if (request.ContainsKey(key))
632 { 672 {
633 string val = (String)request[key]; 673 string val = (String)request[key];
634 queryString = queryString + key + "=" + val + "&"; 674 if (key != "")
675 {
676 queryString = queryString + key + "=" + val + "&";
677 }
678 else
679 {
680 queryString = queryString + val + "&";
681 }
635 } 682 }
636 } 683 }
637
638 if (queryString.Length > 1) 684 if (queryString.Length > 1)
639 queryString = queryString.Substring(0, queryString.Length - 1); 685 queryString = queryString.Substring(0, queryString.Length - 1);
686
640 } 687 }
688
641 } 689 }
642 690
643 //if this machine is behind DNAT/port forwarding, currently this is being 691 //if this machine is behind DNAT/port forwarding, currently this is being
@@ -645,23 +693,34 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
645 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"]; 693 requestData.headers["x-remote-ip"] = requestData.headers["remote_addr"];
646 requestData.headers["x-path-info"] = pathInfo; 694 requestData.headers["x-path-info"] = pathInfo;
647 requestData.headers["x-query-string"] = queryString; 695 requestData.headers["x-query-string"] = queryString;
648 requestData.headers["x-script-url"] = urlData.url; 696 requestData.headers["x-script-url"] = url.url;
649 697
650 urlData.requests.Add(requestID, requestData); 698 //requestData.ev = new ManualResetEvent(false);
651 m_RequestMap.Add(requestID, urlData); 699 lock (url.requests)
652 } 700 {
701 url.requests.Add(requestID, requestData);
702 }
703 lock (m_RequestMap)
704 {
705 //add to request map
706 m_RequestMap.Add(requestID, url);
707 }
653 708
654 urlData.engine.PostScriptEvent( 709 url.engine.PostScriptEvent(url.itemID, "http_request", new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() });
655 urlData.itemID, 710
656 "http_request", 711 //send initial response?
657 new Object[] { requestID.ToString(), request["http-method"].ToString(), request["body"].ToString() }); 712// Hashtable response = new Hashtable();
658 } 713
659 catch (Exception we) 714 return;
660 { 715
661 //Hashtable response = new Hashtable(); 716 }
662 m_log.Warn("[HttpRequestHandler]: http-in request failed"); 717 catch (Exception we)
663 m_log.Warn(we.Message); 718 {
664 m_log.Warn(we.StackTrace); 719 //Hashtable response = new Hashtable();
720 m_log.Warn("[HttpRequestHandler]: http-in request failed");
721 m_log.Warn(we.Message);
722 m_log.Warn(we.StackTrace);
723 }
665 } 724 }
666 } 725 }
667 726
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index 6da2222..ad33f23 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -271,6 +271,8 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
271 return "modInvokeR"; 271 return "modInvokeR";
272 else if (sid.ReturnType == typeof(object[])) 272 else if (sid.ReturnType == typeof(object[]))
273 return "modInvokeL"; 273 return "modInvokeL";
274 else if (sid.ReturnType == typeof(void))
275 return "modInvokeN";
274 276
275 m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); 277 m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
276 } 278 }
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 4cecd85..2fc89fc 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -861,4 +861,4 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
861 return null; 861 return null;
862 } 862 }
863 } 863 }
864} \ No newline at end of file 864}
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index 3484387..1a53a8b 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -96,6 +96,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
96 // private static readonly ILog m_log = 96 // private static readonly ILog m_log =
97 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 97 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
98 98
99 private const int DEBUG_CHANNEL = 2147483647;
100
99 private ListenerManager m_listenerManager; 101 private ListenerManager m_listenerManager;
100 private Queue m_pending; 102 private Queue m_pending;
101 private Queue m_pendingQ; 103 private Queue m_pendingQ;
@@ -366,61 +368,58 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
366 /// <param name='msg'> 368 /// <param name='msg'>
367 /// Message. 369 /// Message.
368 /// </param> 370 /// </param>
369 public void DeliverMessageTo(UUID target, int channel, Vector3 pos, 371 public bool DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg)
370 string name, UUID id, string msg)
371 { 372 {
373 if (channel == DEBUG_CHANNEL)
374 return true;
375
372 // Is id an avatar? 376 // Is id an avatar?
373 ScenePresence sp = m_scene.GetScenePresence(target); 377 ScenePresence sp = m_scene.GetScenePresence(target);
374 378
375 if (sp != null) 379 if (sp != null)
376 { 380 {
377 // ignore if a child agent this is restricted to inside one 381 // Send message to avatar
378 // region 382 if (channel == 0)
379 if (sp.IsChildAgent)
380 return;
381
382 // Channel zero only goes to the avatar
383 // non zero channel messages only go to the attachments of the avatar.
384 if (channel != 0)
385 { 383 {
386 List<SceneObjectGroup> attachments = sp.GetAttachments(); 384 // Channel 0 goes to viewer ONLY
387 if (attachments.Count == 0) 385 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false);
388 return; 386 return true;
387 }
389 388
390 // Get uuid of attachments 389 List<SceneObjectGroup> attachments = sp.GetAttachments();
391 List<UUID> targets = new List<UUID>();
392 foreach (SceneObjectGroup sog in attachments)
393 {
394 if (!sog.IsDeleted)
395 targets.Add(sog.UUID);
396 }
397 390
398 // Need to check each attachment 391 if (attachments.Count == 0)
399 foreach (ListenerInfo li 392 return true;
400 in m_listenerManager.GetListeners(UUID.Zero,
401 channel, name, id, msg))
402 {
403 if (li.GetHostID().Equals(id))
404 continue;
405 393
406 if (m_scene.GetSceneObjectPart( 394 // Get uuid of attachments
407 li.GetHostID()) == null) 395 List<UUID> targets = new List<UUID>();
408 { 396 foreach (SceneObjectGroup sog in attachments)
409 continue; 397 {
410 } 398 if (!sog.IsDeleted)
399 targets.Add(sog.UUID);
400 }
411 401
412 if (targets.Contains(li.GetHostID())) 402 // Need to check each attachment
413 QueueMessage(new ListenerInfo(li, name, id, msg)); 403 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
414 } 404 {
405 if (li.GetHostID().Equals(id))
406 continue;
407
408 if (m_scene.GetSceneObjectPart(li.GetHostID()) == null)
409 continue;
410
411 if (targets.Contains(li.GetHostID()))
412 QueueMessage(new ListenerInfo(li, name, id, msg));
415 } 413 }
416 414
417 return; 415 return true;
418 } 416 }
419 417
420 // No avatar found so look for an object 418 SceneObjectPart part = m_scene.GetSceneObjectPart(target);
421 foreach (ListenerInfo li 419 if (part == null) // Not even an object
422 in m_listenerManager.GetListeners(UUID.Zero, channel, 420 return true; // No error
423 name, id, msg)) 421
422 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg))
424 { 423 {
425 // Dont process if this message is from yourself! 424 // Dont process if this message is from yourself!
426 if (li.GetHostID().Equals(id)) 425 if (li.GetHostID().Equals(id))
@@ -438,7 +437,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
438 } 437 }
439 } 438 }
440 439
441 return; 440 return true;
442 } 441 }
443 442
444 protected void QueueMessage(ListenerInfo li) 443 protected void QueueMessage(ListenerInfo li)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
index 16f42a7..f027810 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
@@ -139,6 +139,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication
139 139
140 #region IAuthenticationService 140 #region IAuthenticationService
141 141
142 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
143 {
144 // Not implemented at the regions
145 realID = UUID.Zero;
146 return string.Empty;
147 }
148
142 public string Authenticate(UUID principalID, string password, int lifetime) 149 public string Authenticate(UUID principalID, string password, int lifetime)
143 { 150 {
144 // Not implemented at the regions 151 // Not implemented at the regions
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 1f782f5..e585c25 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -201,13 +201,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
201 uint regionX = Util.WorldToRegionLoc((uint)x); 201 uint regionX = Util.WorldToRegionLoc((uint)x);
202 uint regionY = Util.WorldToRegionLoc((uint)y); 202 uint regionY = Util.WorldToRegionLoc((uint)y);
203 203
204 // Sanity check
205 if ((Util.RegionToWorldLoc(regionX) != (uint)x) || (Util.RegionToWorldLoc(regionY) != (uint)y))
206 {
207 m_log.WarnFormat("{0} GetRegionByPosition. Bad position requested: not the base of the region. Requested Pos=<{1},{2}>, Should Be=<{3},{4}>",
208 LogHeader, x, y, Util.RegionToWorldLoc(regionX), Util.RegionToWorldLoc(regionY));
209 }
210
211 // First see if it's a neighbour, even if it isn't on this sim. 204 // First see if it's a neighbour, even if it isn't on this sim.
212 // Neighbour data is cached in memory, so this is fast 205 // Neighbour data is cached in memory, so this is fast
213 206
@@ -218,9 +211,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
218 region = rcache.GetRegionByPosition(x, y); 211 region = rcache.GetRegionByPosition(x, y);
219 if (region != null) 212 if (region != null)
220 { 213 {
221 m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache (of region {2}). Pos=<{3},{4}>", 214 //m_log.DebugFormat("{0} GetRegionByPosition. Found region {1} in cache (of region {2}). Pos=<{3},{4}>",
222 LogHeader, region.RegionName, rcache.RegionName, 215 // LogHeader, region.RegionName, rcache.RegionName,
223 Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY)); 216 // Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
224 break; 217 break;
225 } 218 }
226 } 219 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
index ae76288..2961c10 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionCache.cs
@@ -81,22 +81,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
81 { 81 {
82 return new List<GridRegion>(m_neighbours.Values); 82 return new List<GridRegion>(m_neighbours.Values);
83 } 83 }
84 84
85 // Get a region given its base coordinates (in meters).
86 // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
87 // be the base coordinate of the region.
88 // The snapping is technically unnecessary but is harmless because regions are always
89 // multiples of the legacy region size (256).
90 public GridRegion GetRegionByPosition(int x, int y) 85 public GridRegion GetRegionByPosition(int x, int y)
91 { 86 {
92 uint xsnap = (uint)(x / Constants.RegionSize) * Constants.RegionSize; 87 // do actual search by position
93 uint ysnap = (uint)(y / Constants.RegionSize) * Constants.RegionSize; 88 // not the best, but this will not hold that many regions
94 ulong handle = Util.RegionWorldLocToHandle(xsnap, ysnap); 89 GridRegion foundRegion = null;
95 90 foreach(GridRegion r in m_neighbours.Values)
96 if (m_neighbours.ContainsKey(handle)) 91 {
97 return m_neighbours[handle]; 92 if (x >= r.RegionLocX && x < r.RegionLocX + r.RegionSizeX
98 93 && y >= r.RegionLocY && y < r.RegionLocY + r.RegionSizeY)
99 return null; 94 {
95 foundRegion = r;
96 break;
97 }
98 }
99
100 return foundRegion;
100 } 101 }
101 } 102 }
102} 103}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index 25ae689..c33f7f5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -198,4 +198,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
198 Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected"); 198 Assert.That(results.Count, Is.EqualTo(0), "Retrieved linked regions collection is not the number expected");
199 } 199 }
200 } 200 }
201} \ No newline at end of file 201}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 08d6bdd..ef0eec5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -53,6 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
53 /// </remarks> 53 /// </remarks>
54 54
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageServiceModule")] 55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageServiceModule")]
56
56 public class MapImageServiceModule : IMapImageUploadModule, ISharedRegionModule 57 public class MapImageServiceModule : IMapImageUploadModule, ISharedRegionModule
57 { 58 {
58 private static readonly ILog m_log = 59 private static readonly ILog m_log =
@@ -93,9 +94,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
93 if (config == null) 94 if (config == null)
94 return; 95 return;
95 96
96 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime")); 97 int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime", "60"));
97
98 // if refresh is less than zero, disable the module
99 if (refreshminutes < 0) 98 if (refreshminutes < 0)
100 { 99 {
101 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Negative refresh time given in config. Module disabled."); 100 m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: Negative refresh time given in config. Module disabled.");
@@ -128,6 +127,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
128 m_refreshTimer.Interval = m_refreshtime; 127 m_refreshTimer.Interval = m_refreshtime;
129 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh); 128 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
130 129
130
131 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0} min and service object {1}", 131 m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0} min and service object {1}",
132 refreshminutes, service); 132 refreshminutes, service);
133 } 133 }
@@ -218,7 +218,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
218 // If the region/maptile is legacy sized, just upload the one tile like it has always been done 218 // If the region/maptile is legacy sized, just upload the one tile like it has always been done
219 if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize) 219 if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize)
220 { 220 {
221 ConvertAndUploadMaptile(mapTile, 221 ConvertAndUploadMaptile(scene, mapTile,
222 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, 222 scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY,
223 scene.RegionInfo.RegionName); 223 scene.RegionInfo.RegionName);
224 } 224 }
@@ -240,7 +240,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
240 (int)Constants.RegionSize, (int)Constants.RegionSize); 240 (int)Constants.RegionSize, (int)Constants.RegionSize);
241 using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat)) 241 using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat))
242 { 242 {
243 ConvertAndUploadMaptile(subMapTile, 243 ConvertAndUploadMaptile(scene, subMapTile,
244 scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize), 244 scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize),
245 scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize), 245 scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize),
246 scene.Name); 246 scene.Name);
@@ -253,8 +253,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
253 ///<summary> 253 ///<summary>
254 /// 254 ///
255 ///</summary> 255 ///</summary>
256 private void UploadMapTile(IScene scene) 256 public void UploadMapTile(IScene scene)
257 { 257 {
258 m_log.DebugFormat("{0}: upload maptile for {1}", LogHeader, scene.RegionInfo.RegionName);
259
258 // Create a JPG map tile and upload it to the AddMapTile API 260 // Create a JPG map tile and upload it to the AddMapTile API
259 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>(); 261 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
260 if (tileGenerator == null) 262 if (tileGenerator == null)
@@ -265,18 +267,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
265 267
266 using (Bitmap mapTile = tileGenerator.CreateMapTile()) 268 using (Bitmap mapTile = tileGenerator.CreateMapTile())
267 { 269 {
268 if (mapTile != null) 270 // XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there
269 { 271 // is no static map tile.
270 UploadMapTile(scene, mapTile); 272 if (mapTile == null)
271 } 273 return;
272 else 274
273 { 275 UploadMapTile(scene, mapTile);
274 m_log.WarnFormat("{0} Tile image generation failed", LogHeader);
275 }
276 } 276 }
277 } 277 }
278 278
279 private void ConvertAndUploadMaptile(Image tileImage, uint locX, uint locY, string regionName) 279 private void ConvertAndUploadMaptile(IScene scene, Image tileImage, uint locX, uint locY, string regionName)
280 { 280 {
281 byte[] jpgData = Utils.EmptyBytes; 281 byte[] jpgData = Utils.EmptyBytes;
282 282
@@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
288 if (jpgData != Utils.EmptyBytes) 288 if (jpgData != Utils.EmptyBytes)
289 { 289 {
290 string reason = string.Empty; 290 string reason = string.Empty;
291 if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, out reason)) 291 if (!m_MapService.AddMapTile((int)locX, (int)locY, jpgData, scene.RegionInfo.ScopeID, out reason))
292 { 292 {
293 m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader, 293 m_log.DebugFormat("{0} Unable to upload tile image for {1} at {2}-{3}: {4}", LogHeader,
294 regionName, locX, locY, reason); 294 regionName, locX, locY, reason);
@@ -300,4 +300,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
300 } 300 }
301 } 301 }
302 } 302 }
303} \ No newline at end of file 303}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index cc8203e..3755650 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -185,7 +185,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
185 * Agent-related communications 185 * Agent-related communications
186 */ 186 */
187 187
188 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 188 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason)
189 { 189 {
190 if (destination == null) 190 if (destination == null)
191 { 191 {
@@ -204,7 +204,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
204 return false; 204 return false;
205 } 205 }
206 206
207 public bool UpdateAgent(GridRegion destination, AgentData cAgentData) 207 public bool UpdateAgent(GridRegion destination, AgentData cAgentData, EntityTransferContext ctx)
208 { 208 {
209 if (destination == null) 209 if (destination == null)
210 return false; 210 return false;
@@ -268,6 +268,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
268 268
269 } 269 }
270 270
271
271 return m_scenes[destination.RegionID].QueryAccess(agentID, agentHomeURI, viaTeleport, position, features, out reason); 272 return m_scenes[destination.RegionID].QueryAccess(agentID, agentHomeURI, viaTeleport, position, features, out reason);
272 } 273 }
273 274
@@ -305,7 +306,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
305 m_scenes[destination.RegionID].CloseAgent(id, false, auth_token); 306 m_scenes[destination.RegionID].CloseAgent(id, false, auth_token);
306 return true; 307 return true;
307 } 308 }
308
309 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 309 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
310 return false; 310 return false;
311 } 311 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index 1e095ca..0ebdbce 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -160,7 +160,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
160 * Agent-related communications 160 * Agent-related communications
161 */ 161 */
162 162
163 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 163 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason)
164 { 164 {
165 if (destination == null) 165 if (destination == null)
166 { 166 {
@@ -170,27 +170,27 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
170 } 170 }
171 171
172 // Try local first 172 // Try local first
173 if (m_localBackend.CreateAgent(source, destination, aCircuit, teleportFlags, out reason)) 173 if (m_localBackend.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out reason))
174 return true; 174 return true;
175 175
176 // else do the remote thing 176 // else do the remote thing
177 if (!m_localBackend.IsLocalRegion(destination.RegionID)) 177 if (!m_localBackend.IsLocalRegion(destination.RegionID))
178 { 178 {
179 return m_remoteConnector.CreateAgent(source, destination, aCircuit, teleportFlags, out reason); 179 return m_remoteConnector.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out reason);
180 } 180 }
181 return false; 181 return false;
182 } 182 }
183 183
184 public bool UpdateAgent(GridRegion destination, AgentData cAgentData) 184 public bool UpdateAgent(GridRegion destination, AgentData cAgentData, EntityTransferContext ctx)
185 { 185 {
186 if (destination == null) 186 if (destination == null)
187 return false; 187 return false;
188 188
189 // Try local first 189 // Try local first
190 if (m_localBackend.IsLocalRegion(destination.RegionID)) 190 if (m_localBackend.IsLocalRegion(destination.RegionID))
191 return m_localBackend.UpdateAgent(destination, cAgentData); 191 return m_localBackend.UpdateAgent(destination, cAgentData, ctx);
192 192
193 return m_remoteConnector.UpdateAgent(destination, cAgentData); 193 return m_remoteConnector.UpdateAgent(destination, cAgentData, ctx);
194 } 194 }
195 195
196 public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData) 196 public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData)
@@ -236,7 +236,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
236 return false; 236 return false;
237 } 237 }
238 238
239
240 public bool CloseAgent(GridRegion destination, UUID id, string auth_token) 239 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
241 { 240 {
242 if (destination == null) 241 if (destination == null)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 6d4ac39..cf9a7b4 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -129,6 +129,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
129 // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner 129 // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner
130 // user account service?! 130 // user account service?!
131 scene.RegisterModuleInterface<IUserAccountService>(UserAccountService); 131 scene.RegisterModuleInterface<IUserAccountService>(UserAccountService);
132 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
132 } 133 }
133 134
134 public void RemoveRegion(Scene scene) 135 public void RemoveRegion(Scene scene)
@@ -181,6 +182,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
181 return UserAccountService.GetUserAccount(scopeID, Email); 182 return UserAccountService.GetUserAccount(scopeID, Email);
182 } 183 }
183 184
185 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
186 {
187 return null;
188 }
189
184 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 190 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
185 { 191 {
186 return UserAccountService.GetUserAccounts(scopeID, query); 192 return UserAccountService.GetUserAccounts(scopeID, query);
@@ -203,4 +209,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
203 209
204 #endregion 210 #endregion
205 } 211 }
206} \ No newline at end of file 212}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
index 5aa87d3..afbba30 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
@@ -34,6 +34,7 @@ using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
36using OpenSim.Services.Connectors; 36using OpenSim.Services.Connectors;
37using OpenSim.Framework;
37 38
38using OpenMetaverse; 39using OpenMetaverse;
39 40
@@ -103,6 +104,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
103 return; 104 return;
104 105
105 scene.RegisterModuleInterface<IUserAccountService>(this); 106 scene.RegisterModuleInterface<IUserAccountService>(this);
107 scene.RegisterModuleInterface<IUserAccountCacheModule>(m_Cache);
108
109 scene.EventManager.OnNewClient += OnNewClient;
106 } 110 }
107 111
108 public void RemoveRegion(Scene scene) 112 public void RemoveRegion(Scene scene)
@@ -117,6 +121,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
117 return; 121 return;
118 } 122 }
119 123
124 // When a user actually enters the sim, clear them from
125 // cache so the sim will have the current values for
126 // flags, title, etc. And country, don't forget country!
127 private void OnNewClient(IClientAPI client)
128 {
129 m_Cache.Remove(client.Name);
130 }
131
120 #region Overwritten methods from IUserAccountService 132 #region Overwritten methods from IUserAccountService
121 133
122 public override UserAccount GetUserAccount(UUID scopeID, UUID userID) 134 public override UserAccount GetUserAccount(UUID scopeID, UUID userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
index ed52e48..53610d9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs
@@ -34,7 +34,7 @@ using log4net;
34 34
35namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts 35namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
36{ 36{
37 public class UserAccountCache 37 public class UserAccountCache : IUserAccountCacheModule
38 { 38 {
39 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours! 39 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours!
40 40
@@ -97,5 +97,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
97 97
98 return null; 98 return null;
99 } 99 }
100
101 public void Remove(string name)
102 {
103 if (!m_NameCache.Contains(name))
104 return;
105
106 UUID uuid = UUID.Zero;
107 if (m_NameCache.TryGetValue(name, out uuid))
108 {
109 m_NameCache.Remove(name);
110 m_UUIDCache.Remove(uuid);
111 }
112 }
100 } 113 }
101} 114}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 9c6706f..406f4a8 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -160,10 +160,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
160 160
161 private IAssetService m_assetService = null; 161 private IAssetService m_assetService = null;
162 162
163
164 private UUID m_defaultUser; 163 private UUID m_defaultUser;
165 164
166 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string,object>options) 165 public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string, object> options)
167 { 166 {
168 m_rootScene = scene; 167 m_rootScene = scene;
169 168
@@ -172,7 +171,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
172 m_defaultUser = (UUID)options["default-user"]; 171 m_defaultUser = (UUID)options["default-user"];
173 m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString()); 172 m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString());
174 } 173 }
175 else 174 else
176 { 175 {
177 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; 176 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
178 } 177 }
@@ -189,8 +188,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
189 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); 188 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
190 m_log.Error(e); 189 m_log.Error(e);
191 } 190 }
192 191
193 m_errorMessage = String.Empty; 192 m_errorMessage = String.Empty;
193
194 m_merge = options.ContainsKey("merge"); 194 m_merge = options.ContainsKey("merge");
195 m_forceTerrain = options.ContainsKey("force-terrain"); 195 m_forceTerrain = options.ContainsKey("force-terrain");
196 m_forceParcels = options.ContainsKey("force-parcels"); 196 m_forceParcels = options.ContainsKey("force-parcels");
@@ -199,10 +199,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
199 m_requestId = requestId; 199 m_requestId = requestId;
200 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero; 200 m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
201 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f; 201 m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
202 m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"] 202 m_rotationCenter = options.ContainsKey("rotation-center") ? (Vector3)options["rotation-center"]
203 : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f); 203 : new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 0f);
204 204
205 // Zero can never be a valid user or group id 205 // Zero can never be a valid user id (or group)
206 m_validUserUuids[UUID.Zero] = false; 206 m_validUserUuids[UUID.Zero] = false;
207 m_validGroupUuids[UUID.Zero] = false; 207 m_validGroupUuids[UUID.Zero] = false;
208 208
@@ -210,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
210 m_assetService = m_rootScene.AssetService; 210 m_assetService = m_rootScene.AssetService;
211 } 211 }
212 212
213 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object>options) 213 public ArchiveReadRequest(Scene scene, Stream loadStream, Guid requestId, Dictionary<string, object> options)
214 { 214 {
215 m_rootScene = scene; 215 m_rootScene = scene;
216 m_loadPath = null; 216 m_loadPath = null;
@@ -220,7 +220,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
220 m_requestId = requestId; 220 m_requestId = requestId;
221 221
222 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; 222 m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
223 223
224 // Zero can never be a valid user id 224 // Zero can never be a valid user id
225 m_validUserUuids[UUID.Zero] = false; 225 m_validUserUuids[UUID.Zero] = false;
226 226
@@ -523,7 +523,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
523 } 523 }
524 } 524 }
525 525
526
527 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); 526 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
528 527
529 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned 528 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
@@ -600,6 +599,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
600 // being no copy/no mod for everyone 599 // being no copy/no mod for everyone
601 lock (part.TaskInventory) 600 lock (part.TaskInventory)
602 { 601 {
602 // And zap any troublesome sit target information
603 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
604 part.SitTargetPosition = new Vector3(0, 0, 0);
605
606 // Fix ownership/creator of inventory items
607 // Not doing so results in inventory items
608 // being no copy/no mod for everyone
609 part.TaskInventory.LockItemsForRead(true);
610
603 TaskInventoryDictionary inv = part.TaskInventory; 611 TaskInventoryDictionary inv = part.TaskInventory;
604 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 612 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
605 { 613 {
@@ -620,11 +628,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
620 if (!ResolveGroupUuid(kvp.Value.GroupID)) 628 if (!ResolveGroupUuid(kvp.Value.GroupID))
621 kvp.Value.GroupID = UUID.Zero; 629 kvp.Value.GroupID = UUID.Zero;
622 } 630 }
631 part.TaskInventory.LockItemsForRead(false);
632
623 } 633 }
624 } 634 }
625 } 635 }
626 636
627
628 /// <summary> 637 /// <summary>
629 /// Load serialized parcels. 638 /// Load serialized parcels.
630 /// </summary> 639 /// </summary>
@@ -645,7 +654,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
645 parcel.AABBMin += parcelDisp; 654 parcel.AABBMin += parcelDisp;
646 parcel.AABBMax += parcelDisp; 655 parcel.AABBMax += parcelDisp;
647 } 656 }
648 657
649 // Validate User and Group UUID's 658 // Validate User and Group UUID's
650 659
651 if (!ResolveGroupUuid(parcel.GroupID)) 660 if (!ResolveGroupUuid(parcel.GroupID))
@@ -660,14 +669,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
660 } 669 }
661 else 670 else
662 { 671 {
663 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; 672 parcel.OwnerID = m_defaultUser;
673 parcel.GroupID = UUID.Zero;
664 parcel.IsGroupOwned = false; 674 parcel.IsGroupOwned = false;
665 } 675 }
666 } 676 }
667 else 677 else
668 { 678 {
669 if (!ResolveUserUuid(scene, parcel.OwnerID)) 679 if (!ResolveUserUuid(scene, parcel.OwnerID))
670 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; 680 parcel.OwnerID = m_defaultUser;
681
682 if (!ResolveGroupUuid(parcel.GroupID))
683 parcel.GroupID = UUID.Zero;
671 } 684 }
672 685
673 List<LandAccessEntry> accessList = new List<LandAccessEntry>(); 686 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
@@ -918,7 +931,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
918 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) 931 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
919 { 932 {
920 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); 933 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
921
922 using (MemoryStream ms = new MemoryStream(data)) 934 using (MemoryStream ms = new MemoryStream(data))
923 { 935 {
924 if (m_displacement != Vector3.Zero || m_rotation != 0f) 936 if (m_displacement != Vector3.Zero || m_rotation != 0f)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index 6a09caf..4178a57 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -111,17 +111,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
111 String defaultUser = ""; 111 String defaultUser = "";
112 float rotation = 0f; 112 float rotation = 0f;
113 Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0); 113 Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0);
114 114
115
115 OptionSet options = new OptionSet(); 116 OptionSet options = new OptionSet();
116 options.Add("m|merge", delegate (string v) { mergeOar = (v != null); }); 117 options.Add("m|merge", delegate(string v) { mergeOar = (v != null); });
117 options.Add("s|skip-assets", delegate (string v) { skipAssets = (v != null); }); 118 options.Add("s|skip-assets", delegate(string v) { skipAssets = (v != null); });
118 options.Add("force-terrain", delegate (string v) { forceTerrain = (v != null); }); 119 options.Add("force-terrain", delegate(string v) { forceTerrain = (v != null); });
119 options.Add("forceterrain", delegate (string v) { forceTerrain = (v != null); }); // downward compatibility 120 options.Add("forceterrain", delegate(string v) { forceTerrain = (v != null); }); // downward compatibility
120 options.Add("force-parcels", delegate (string v) { forceParcels = (v != null); }); 121 options.Add("force-parcels", delegate(string v) { forceParcels = (v != null); });
121 options.Add("forceparcels", delegate (string v) { forceParcels = (v != null); }); // downward compatibility 122 options.Add("forceparcels", delegate(string v) { forceParcels = (v != null); }); // downward compatibility
122 options.Add("no-objects", delegate (string v) { noObjects = (v != null); }); 123 options.Add("no-objects", delegate(string v) { noObjects = (v != null); });
123 options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; }); 124 options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; });
124 options.Add("displacement=", delegate (string v) { 125 options.Add("displacement=", delegate(string v)
126 {
125 try 127 try
126 { 128 {
127 displacement = v == null ? Vector3.Zero : Vector3.Parse(v); 129 displacement = v == null ? Vector3.Zero : Vector3.Parse(v);
@@ -148,7 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
148 // Convert to radians for internals 150 // Convert to radians for internals
149 rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI; 151 rotation = Util.Clamp<float>(rotation, -359f, 359f) / 180f * (float)Math.PI;
150 }); 152 });
151 options.Add("rotation-center=", delegate (string v) { 153 options.Add("rotation-center=", delegate(string v)
154 {
152 try 155 try
153 { 156 {
154 rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v); 157 rotationCenter = v == null ? Vector3.Zero : Vector3.Parse(v);
@@ -288,12 +291,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
288 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 291 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
289 DearchiveRegion(loadPath, Guid.Empty, archiveOptions); 292 DearchiveRegion(loadPath, Guid.Empty, archiveOptions);
290 } 293 }
291 294
292 public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options) 295 public void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string, object> options)
293 { 296 {
294 m_log.InfoFormat( 297 m_log.InfoFormat(
295 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath); 298 "[ARCHIVER]: Loading archive to region {0} from {1}", Scene.RegionInfo.RegionName, loadPath);
296 299
297 new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion(); 300 new ArchiveReadRequest(Scene, loadPath, requestId, options).DearchiveRegion();
298 } 301 }
299 302
@@ -302,7 +305,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
302 Dictionary<string, object> archiveOptions = new Dictionary<string, object>(); 305 Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
303 DearchiveRegion(loadStream, Guid.Empty, archiveOptions); 306 DearchiveRegion(loadStream, Guid.Empty, archiveOptions);
304 } 307 }
305
306 public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options) 308 public void DearchiveRegion(Stream loadStream, Guid requestId, Dictionary<string, object> options)
307 { 309 {
308 new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion(); 310 new ArchiveReadRequest(Scene, loadStream, requestId, options).DearchiveRegion();
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index db66c83..895b55d 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -271,18 +271,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
271 271
272 if (asset != null) 272 if (asset != null)
273 { 273 {
274 if (m_options.ContainsKey("verbose")) 274// m_log.DebugFormat("[ARCHIVER]: Writing asset {0}", id);
275 m_log.InfoFormat("[ARCHIVER]: Writing asset {0}", id);
276
277 m_foundAssetUuids.Add(asset.FullID); 275 m_foundAssetUuids.Add(asset.FullID);
278 276
279 m_assetsArchiver.WriteAsset(PostProcess(asset)); 277 m_assetsArchiver.WriteAsset(PostProcess(asset));
280 } 278 }
281 else 279 else
282 { 280 {
283 if (m_options.ContainsKey("verbose")) 281// m_log.DebugFormat("[ARCHIVER]: Recording asset {0} as not found", id);
284 m_log.InfoFormat("[ARCHIVER]: Recording asset {0} as not found", id);
285
286 m_notFoundAssetUuids.Add(new UUID(id)); 282 m_notFoundAssetUuids.Add(new UUID(id));
287 } 283 }
288 284
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 80fa08a..3ded00c 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -68,6 +68,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
68 public event ChangeDelegate OnEstateInfoChange; 68 public event ChangeDelegate OnEstateInfoChange;
69 public event MessageDelegate OnEstateMessage; 69 public event MessageDelegate OnEstateMessage;
70 70
71 private int m_delayCount = 0;
72
71 #region Region Module interface 73 #region Region Module interface
72 74
73 public string Name { get { return "EstateManagementModule"; } } 75 public string Name { get { return "EstateManagementModule"; } }
@@ -95,6 +97,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
95 97
96 m_commands = new EstateManagementCommands(this); 98 m_commands = new EstateManagementCommands(this);
97 m_commands.Initialise(); 99 m_commands.Initialise();
100
101 m_regionChangeTimer.Interval = 10000;
102 m_regionChangeTimer.Elapsed += RaiseRegionInfoChange;
103 m_regionChangeTimer.AutoReset = false;
98 } 104 }
99 105
100 public void RemoveRegion(Scene scene) {} 106 public void RemoveRegion(Scene scene) {}
@@ -142,6 +148,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
142 flags |= RegionFlags.AllowParcelChanges; 148 flags |= RegionFlags.AllowParcelChanges;
143 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch) 149 if (Scene.RegionInfo.RegionSettings.BlockShowInSearch)
144 flags |= RegionFlags.BlockParcelSearch; 150 flags |= RegionFlags.BlockParcelSearch;
151 if (Scene.RegionInfo.RegionSettings.GodBlockSearch)
152 flags |= (RegionFlags)(1 << 11);
153 if (Scene.RegionInfo.RegionSettings.Casino)
154 flags |= (RegionFlags)(1 << 10);
145 155
146 if (Scene.RegionInfo.RegionSettings.FixedSun) 156 if (Scene.RegionInfo.RegionSettings.FixedSun)
147 flags |= RegionFlags.SunFixed; 157 flags |= RegionFlags.SunFixed;
@@ -194,6 +204,14 @@ namespace OpenSim.Region.CoreModules.World.Estate
194 change(Scene.RegionInfo.RegionID); 204 change(Scene.RegionInfo.RegionID);
195 } 205 }
196 206
207 protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e)
208 {
209 ChangeDelegate change = OnRegionInfoChange;
210
211 if (change != null)
212 change(Scene.RegionInfo.RegionID);
213 }
214
197 public void TriggerRegionInfoChange() 215 public void TriggerRegionInfoChange()
198 { 216 {
199 m_regionChangeTimer.Stop(); 217 m_regionChangeTimer.Stop();
@@ -587,6 +605,16 @@ namespace OpenSim.Region.CoreModules.World.Estate
587 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 605 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
588 if (restartModule != null) 606 if (restartModule != null)
589 { 607 {
608 if (timeInSeconds == -1)
609 {
610 m_delayCount++;
611 if (m_delayCount > 3)
612 return;
613
614 restartModule.DelayRestart(3600, "Restart delayed by region manager");
615 return;
616 }
617
590 List<int> times = new List<int>(); 618 List<int> times = new List<int>();
591 while (timeInSeconds > 0) 619 while (timeInSeconds > 0)
592 { 620 {
@@ -1477,7 +1505,8 @@ namespace OpenSim.Region.CoreModules.World.Estate
1477 sendRegionHandshake(client); 1505 sendRegionHandshake(client);
1478 } 1506 }
1479 1507
1480 private uint GetEstateFlags() 1508
1509 public uint GetEstateFlags()
1481 { 1510 {
1482 RegionFlags flags = RegionFlags.None; 1511 RegionFlags flags = RegionFlags.None;
1483 1512
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
index 73c592d..378826d 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
@@ -40,23 +40,33 @@ namespace OpenSim.Region.CoreModules.World.Land
40 //Land types set with flags in ParcelOverlay. 40 //Land types set with flags in ParcelOverlay.
41 //Only one of these can be used. 41 //Only one of these can be used.
42 public const float BAN_LINE_SAFETY_HIEGHT = 100; 42 public const float BAN_LINE_SAFETY_HIEGHT = 100;
43 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 128; //Equals 10000000
44 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 64; //Equals 01000000
45 43
46 //RequestResults (I think these are right, they seem to work): 44 //RequestResults (I think these are right, they seem to work):
47 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land 45 public const int LAND_RESULT_MULTIPLE = 1; // The request they made contained more than a single peice of land
48 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land 46 public const int LAND_RESULT_SINGLE = 0; // The request they made contained only a single piece of land
49 47
50 //ParcelSelectObjects 48 //ParcelSelectObjects
49 public const int LAND_SELECT_OBJECTS_OWNER = 2;
51 public const int LAND_SELECT_OBJECTS_GROUP = 4; 50 public const int LAND_SELECT_OBJECTS_GROUP = 4;
52 public const int LAND_SELECT_OBJECTS_OTHER = 8; 51 public const int LAND_SELECT_OBJECTS_OTHER = 8;
53 public const int LAND_SELECT_OBJECTS_OWNER = 2; 52
54 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101 53
55 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100 54 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000
56 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010 55 // types 1 to 7 are exclusive
57 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001 56 public const byte LAND_TYPE_OWNED_BY_OTHER = 1; //Equals 00000001
57 public const byte LAND_TYPE_OWNED_BY_GROUP = 2; //Equals 00000010
58 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011 58 public const byte LAND_TYPE_OWNED_BY_REQUESTER = 3; //Equals 00000011
59 public const byte LAND_TYPE_PUBLIC = 0; //Equals 00000000 59 public const byte LAND_TYPE_IS_FOR_SALE = 4; //Equals 00000100
60 public const byte LAND_TYPE_IS_BEING_AUCTIONED = 5; //Equals 00000101
61 public const byte LAND_TYPE_unused6 = 6;
62 public const byte LAND_TYPE_unused7 = 7;
63 // next are flags
64 public const byte LAND_FLAG_unused8 = 0x08; // this may become excluside in future
65 public const byte LAND_FLAG_HIDEAVATARS = 0x10;
66 public const byte LAND_FLAG_LOCALSOUND = 0x20;
67 public const byte LAND_FLAG_PROPERTY_BORDER_WEST = 0x40; //Equals 01000000
68 public const byte LAND_FLAG_PROPERTY_BORDER_SOUTH = 0x80; //Equals 10000000
69
60 70
61 //These are other constants. Yay! 71 //These are other constants. Yay!
62 public const int START_LAND_LOCAL_ID = 1; 72 public const int START_LAND_LOCAL_ID = 1;
@@ -203,7 +213,13 @@ namespace OpenSim.Region.CoreModules.World.Land
203 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime); 213 m_landManagementModule.setParcelOtherCleanTime(remoteClient, localID, otherCleanTime);
204 } 214 }
205 } 215 }
206 216 public void sendClientInitialLandInfo(IClientAPI remoteClient)
217 {
218 if (m_landManagementModule != null)
219 {
220 m_landManagementModule.sendClientInitialLandInfo(remoteClient);
221 }
222 }
207 #endregion 223 #endregion
208 } 224 }
209} 225}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 92f6c1b..ad6793f 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -69,6 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land
69 /// <summary> 69 /// <summary>
70 /// Minimum land unit size in region co-ordinates. 70 /// Minimum land unit size in region co-ordinates.
71 /// </summary> 71 /// </summary>
72
72 public const int LandUnit = 4; 73 public const int LandUnit = 4;
73 74
74 private static readonly string remoteParcelRequestPath = "0009/"; 75 private static readonly string remoteParcelRequestPath = "0009/";
@@ -89,21 +90,26 @@ namespace OpenSim.Region.CoreModules.World.Land
89 /// <value> 90 /// <value>
90 /// Land objects keyed by local id 91 /// Land objects keyed by local id
91 /// </value> 92 /// </value>
92 private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>(); 93// private readonly Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
94
95 //ubit: removed the readonly so i can move it around
96 private Dictionary<int, ILandObject> m_landList = new Dictionary<int, ILandObject>();
93 97
94 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 98 private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
95 99
96 private bool m_allowedForcefulBans = true; 100 private bool m_allowedForcefulBans = true;
101 private UUID DefaultGodParcelGroup;
102 private string DefaultGodParcelName;
97 103
98 // caches ExtendedLandData 104 // caches ExtendedLandData
99 private Cache parcelInfoCache; 105 private Cache parcelInfoCache;
100 106
101
102 /// <summary> 107 /// <summary>
103 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions. 108 /// Record positions that avatar's are currently being forced to move to due to parcel entry restrictions.
104 /// </summary> 109 /// </summary>
105 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>(); 110 private Dictionary<UUID, Vector3> forcedPosition = new Dictionary<UUID, Vector3>();
106 111
112
107 // Enables limiting parcel layer info transmission when doing simple updates 113 // Enables limiting parcel layer info transmission when doing simple updates
108 private bool shouldLimitParcelLayerInfoToViewDistance { get; set; } 114 private bool shouldLimitParcelLayerInfoToViewDistance { get; set; }
109 // "View distance" for sending parcel layer info if asked for from a view point in the region 115 // "View distance" for sending parcel layer info if asked for from a view point in the region
@@ -125,6 +131,8 @@ namespace OpenSim.Region.CoreModules.World.Land
125 { 131 {
126 shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance); 132 shouldLimitParcelLayerInfoToViewDistance = landManagementConfig.GetBoolean("LimitParcelLayerUpdateDistance", shouldLimitParcelLayerInfoToViewDistance);
127 parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance); 133 parcelLayerViewDistance = landManagementConfig.GetInt("ParcelLayerViewDistance", parcelLayerViewDistance);
134 DefaultGodParcelGroup = new UUID(landManagementConfig.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString()));
135 DefaultGodParcelName = landManagementConfig.GetString("DefaultAdministratorParcelName", "Default Parcel");
128 } 136 }
129 } 137 }
130 138
@@ -132,6 +140,7 @@ namespace OpenSim.Region.CoreModules.World.Land
132 { 140 {
133 m_scene = scene; 141 m_scene = scene;
134 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; 142 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit];
143
135 landChannel = new LandChannel(scene, this); 144 landChannel = new LandChannel(scene, this);
136 145
137 parcelInfoCache = new Cache(); 146 parcelInfoCache = new Cache();
@@ -154,7 +163,7 @@ namespace OpenSim.Region.CoreModules.World.Land
154 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; 163 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
155 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; 164 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
156 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; 165 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
157 166
158 lock (m_scene) 167 lock (m_scene)
159 { 168 {
160 m_scene.LandChannel = (ILandChannel)landChannel; 169 m_scene.LandChannel = (ILandChannel)landChannel;
@@ -204,13 +213,14 @@ namespace OpenSim.Region.CoreModules.World.Land
204 client.OnParcelFreezeUser += ClientOnParcelFreezeUser; 213 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
205 client.OnSetStartLocationRequest += ClientOnSetHome; 214 client.OnSetStartLocationRequest += ClientOnSetHome;
206 215
207 216/* avatar is still a child here position is unknown
208 EntityBase presenceEntity; 217 EntityBase presenceEntity;
209 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) 218 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
210 { 219 {
211 SendLandUpdate((ScenePresence)presenceEntity, true); 220 SendLandUpdate((ScenePresence)presenceEntity, true);
212 SendParcelOverlay(client); 221 SendParcelOverlay(client);
213 } 222 }
223*/
214 } 224 }
215 225
216 public void EventMakeChildAgent(ScenePresence avatar) 226 public void EventMakeChildAgent(ScenePresence avatar)
@@ -220,48 +230,6 @@ namespace OpenSim.Region.CoreModules.World.Land
220 230
221 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 231 void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
222 { 232 {
223 //If we are forcing a position for them to go
224 if (forcedPosition.ContainsKey(remoteClient.AgentId))
225 {
226 ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId);
227
228 //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND
229 //When the avatar walks into a ban line on the ground, it prevents getting stuck
230 agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
231
232 //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines
233 if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) < .2)
234 {
235// m_log.DebugFormat(
236// "[LAND MANAGEMENT MODULE]: Stopping force position of {0} because {1} is close enough to {2}",
237// clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]);
238
239 forcedPosition.Remove(remoteClient.AgentId);
240 }
241 //if we are far away, teleport
242 else if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]) > 3)
243 {
244 Vector3 forcePosition = forcedPosition[remoteClient.AgentId];
245// m_log.DebugFormat(
246// "[LAND MANAGEMENT MODULE]: Teleporting out {0} because {1} is too far from avatar position {2}",
247// clientAvatar.Name, clientAvatar.AbsolutePosition, forcePosition);
248
249 m_scene.RequestTeleportLocation(remoteClient, m_scene.RegionInfo.RegionHandle,
250 forcePosition, clientAvatar.Lookat, (uint)Constants.TeleportFlags.ForceRedirect);
251
252 forcedPosition.Remove(remoteClient.AgentId);
253 }
254 else
255 {
256// m_log.DebugFormat(
257// "[LAND MANAGEMENT MODULE]: Forcing {0} from {1} to {2}",
258// clientAvatar.Name, clientAvatar.AbsolutePosition, forcedPosition[remoteClient.AgentId]);
259
260 //Forces them toward the forced position we want if they aren't there yet
261 agentData.UseClientAgentPosition = true;
262 agentData.ClientAgentPosition = forcedPosition[remoteClient.AgentId];
263 }
264 }
265 } 233 }
266 234
267 public void Close() 235 public void Close()
@@ -314,6 +282,7 @@ namespace OpenSim.Region.CoreModules.World.Land
314 { 282 {
315 m_landList.Clear(); 283 m_landList.Clear();
316 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; 284 m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1;
285
317 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; 286 m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit];
318 } 287 }
319 } 288 }
@@ -324,16 +293,16 @@ namespace OpenSim.Region.CoreModules.World.Land
324 /// <returns>The parcel created.</returns> 293 /// <returns>The parcel created.</returns>
325 protected ILandObject CreateDefaultParcel() 294 protected ILandObject CreateDefaultParcel()
326 { 295 {
327 m_log.DebugFormat( 296 m_log.DebugFormat("{0} Creating default parcel for region {1}", LogHeader, m_scene.RegionInfo.RegionName);
328 "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName); 297
329 298 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
330 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 299
331 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, 300 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0,
332 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY)); 301 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY));
333 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 302 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
334 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 303 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
335 304
336 return AddLandObject(fullSimParcel); 305 return AddLandObject(fullSimParcel);
337 } 306 }
338 307
339 public List<ILandObject> AllParcels() 308 public List<ILandObject> AllParcels()
@@ -382,10 +351,17 @@ namespace OpenSim.Region.CoreModules.World.Land
382 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) 351 private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position)
383 { 352 {
384 if (m_scene.Permissions.IsGod(avatar.UUID)) return; 353 if (m_scene.Permissions.IsGod(avatar.UUID)) return;
385 if (position.HasValue) 354
386 { 355 if (!position.HasValue)
387 forcedPosition[avatar.ControllingClient.AgentId] = (Vector3)position; 356 return;
388 } 357
358// land should have no word on avatar physics
359// bool isFlying = avatar.PhysicsActor.Flying;
360// avatar.RemoveFromPhysicalScene();
361
362 avatar.AbsolutePosition = (Vector3)position;
363
364// avatar.AddToPhysicalScene(isFlying);
389 } 365 }
390 366
391 public void SendYouAreRestrictedNotice(ScenePresence avatar) 367 public void SendYouAreRestrictedNotice(ScenePresence avatar)
@@ -405,36 +381,14 @@ namespace OpenSim.Region.CoreModules.World.Land
405 } 381 }
406 382
407 if (parcelAvatarIsEntering != null) 383 if (parcelAvatarIsEntering != null)
408 { 384 EnforceBans(parcelAvatarIsEntering, avatar);
409 if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT)
410 {
411 if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID))
412 {
413 SendYouAreBannedNotice(avatar);
414 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
415 }
416 else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID))
417 {
418 SendYouAreRestrictedNotice(avatar);
419 ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar));
420 }
421 else
422 {
423 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
424 }
425 }
426 else
427 {
428 avatar.sentMessageAboutRestrictedParcelFlyingDown = true;
429 }
430 }
431 } 385 }
432 } 386 }
433 387
434 public void SendOutNearestBanLine(IClientAPI client) 388 public void SendOutNearestBanLine(IClientAPI client)
435 { 389 {
436 ScenePresence sp = m_scene.GetScenePresence(client.AgentId); 390 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
437 if (sp == null || sp.IsChildAgent) 391 if (sp == null)
438 return; 392 return;
439 393
440 List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition); 394 List<ILandObject> checkLandParcels = ParcelsNearPoint(sp.AbsolutePosition);
@@ -454,32 +408,44 @@ namespace OpenSim.Region.CoreModules.World.Land
454 return; 408 return;
455 } 409 }
456 410
411 public void sendClientInitialLandInfo(IClientAPI remoteClient)
412 {
413 ScenePresence avatar;
414
415 if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out avatar))
416 return;
417
418
419 if (!avatar.IsChildAgent)
420 {
421 ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
422 if (over == null)
423 return;
424
425 avatar.currentParcelUUID = over.LandData.GlobalID;
426 over.SendLandUpdateToClient(avatar.ControllingClient);
427 }
428 SendParcelOverlay(remoteClient);
429 }
430
457 public void SendLandUpdate(ScenePresence avatar, bool force) 431 public void SendLandUpdate(ScenePresence avatar, bool force)
458 { 432 {
459 ILandObject over = GetLandObject((int)Math.Min(((int)m_scene.RegionInfo.RegionSizeX - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.X))), 433 if (avatar.IsChildAgent)
460 (int)Math.Min(((int)m_scene.RegionInfo.RegionSizeY - 1), Math.Max(0, Math.Round(avatar.AbsolutePosition.Y)))); 434 return;
435
436 ILandObject over = GetLandObjectClipedXY(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
461 437
462 if (over != null) 438 if (over != null)
463 { 439 {
464 if (force) 440 bool NotsameID = (avatar.currentParcelUUID != over.LandData.GlobalID);
465 { 441 if (force || NotsameID)
466 if (!avatar.IsChildAgent)
467 {
468 over.SendLandUpdateToClient(avatar.ControllingClient);
469 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
470 m_scene.RegionInfo.RegionID);
471 }
472 }
473
474 if (avatar.currentParcelUUID != over.LandData.GlobalID)
475 { 442 {
476 if (!avatar.IsChildAgent) 443 over.SendLandUpdateToClient(avatar.ControllingClient);
477 { 444// sl doesnt seem to send this now, as it used 2
478 over.SendLandUpdateToClient(avatar.ControllingClient); 445// SendParcelOverlay(avatar.ControllingClient);
479 avatar.currentParcelUUID = over.LandData.GlobalID; 446 avatar.currentParcelUUID = over.LandData.GlobalID;
480 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID, 447 m_scene.EventManager.TriggerAvatarEnteringNewParcel(avatar, over.LandData.LocalID,
481 m_scene.RegionInfo.RegionID); 448 m_scene.RegionInfo.RegionID);
482 }
483 } 449 }
484 } 450 }
485 } 451 }
@@ -531,6 +497,7 @@ namespace OpenSim.Region.CoreModules.World.Land
531 //when we are finally in a safe place, lets release the forced position lock 497 //when we are finally in a safe place, lets release the forced position lock
532 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId); 498 forcedPosition.Remove(clientAvatar.ControllingClient.AgentId);
533 } 499 }
500 EnforceBans(parcel, clientAvatar);
534 } 501 }
535 } 502 }
536 503
@@ -589,7 +556,7 @@ namespace OpenSim.Region.CoreModules.World.Land
589 requiredPowers = GroupPowers.LandManageBanned; 556 requiredPowers = GroupPowers.LandManageBanned;
590 557
591 if (m_scene.Permissions.CanEditParcelProperties(agentID, 558 if (m_scene.Permissions.CanEditParcelProperties(agentID,
592 land, requiredPowers)) 559 land, requiredPowers, false))
593 { 560 {
594 land.UpdateAccessList(flags, transactionID, sequenceID, 561 land.UpdateAccessList(flags, transactionID, sequenceID,
595 sections, entries, remote_client); 562 sections, entries, remote_client);
@@ -623,14 +590,11 @@ namespace OpenSim.Region.CoreModules.World.Land
623 new_land.LandData.LocalID = newLandLocalID; 590 new_land.LandData.LocalID = newLandLocalID;
624 591
625 bool[,] landBitmap = new_land.GetLandBitmap(); 592 bool[,] landBitmap = new_land.GetLandBitmap();
626 // m_log.DebugFormat("{0} AddLandObject. new_land.bitmapSize=({1},{2}). newLocalID={3}",
627 // LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), newLandLocalID);
628
629 if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1)) 593 if (landBitmap.GetLength(0) != m_landIDList.GetLength(0) || landBitmap.GetLength(1) != m_landIDList.GetLength(1))
630 { 594 {
631 // Going to variable sized regions can cause mismatches 595 // Going to variable sized regions can cause mismatches
632 m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})", 596 m_log.ErrorFormat("{0} AddLandObject. Added land bitmap different size than region ID map. bitmapSize=({1},{2}), landIDSize=({3},{4})",
633 LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1) ); 597 LogHeader, landBitmap.GetLength(0), landBitmap.GetLength(1), m_landIDList.GetLength(0), m_landIDList.GetLength(1));
634 } 598 }
635 else 599 else
636 { 600 {
@@ -652,7 +616,7 @@ namespace OpenSim.Region.CoreModules.World.Land
652 { 616 {
653 m_log.ErrorFormat( 617 m_log.ErrorFormat(
654 "{0}: Cannot add parcel \"{1}\", local ID {2} at tile {3},{4} because this is still occupied by parcel \"{5}\", local ID {6} in {7}", 618 "{0}: Cannot add parcel \"{1}\", local ID {2} at tile {3},{4} because this is still occupied by parcel \"{5}\", local ID {6} in {7}",
655 LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y, 619 LogHeader, new_land.LandData.Name, new_land.LandData.LocalID, x, y,
656 lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name); 620 lastRecordedLo.LandData.Name, lastRecordedLo.LandData.LocalID, m_scene.Name);
657 621
658 return null; 622 return null;
@@ -668,10 +632,10 @@ namespace OpenSim.Region.CoreModules.World.Land
668 { 632 {
669 if (landBitmap[x, y]) 633 if (landBitmap[x, y])
670 { 634 {
671 // m_log.DebugFormat( 635 // m_log.DebugFormat(
672 // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}", 636 // "[LAND MANAGEMENT MODULE]: Registering parcel {0} for land co-ord ({1}, {2}) on {3}",
673 // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName); 637 // new_land.LandData.Name, x, y, m_scene.RegionInfo.RegionName);
674 638
675 m_landIDList[x, y] = newLandLocalID; 639 m_landIDList[x, y] = newLandLocalID;
676 } 640 }
677 } 641 }
@@ -723,27 +687,28 @@ namespace OpenSim.Region.CoreModules.World.Land
723 /// </summary> 687 /// </summary>
724 public void Clear(bool setupDefaultParcel) 688 public void Clear(bool setupDefaultParcel)
725 { 689 {
726 List<ILandObject> parcels; 690 Dictionary<int, ILandObject> landworkList;
691 // move to work pointer since we are deleting it all
727 lock (m_landList) 692 lock (m_landList)
728 { 693 {
729 parcels = new List<ILandObject>(m_landList.Values); 694 landworkList = m_landList;
695 m_landList = new Dictionary<int, ILandObject>();
730 } 696 }
731 697
732 foreach (ILandObject lo in parcels) 698 // this 2 methods have locks (now)
699 ResetSimLandObjects();
700
701 if (setupDefaultParcel)
702 CreateDefaultParcel();
703
704 // fire outside events unlocked
705 foreach (ILandObject lo in landworkList.Values)
733 { 706 {
734 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); 707 //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID);
735 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); 708 m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID);
736 } 709 }
710 landworkList.Clear();
737 711
738 lock (m_landList)
739 {
740 m_landList.Clear();
741
742 ResetSimLandObjects();
743 }
744
745 if (setupDefaultParcel)
746 CreateDefaultParcel();
747 } 712 }
748 713
749 private void performFinalLandJoin(ILandObject master, ILandObject slave) 714 private void performFinalLandJoin(ILandObject master, ILandObject slave)
@@ -787,58 +752,37 @@ namespace OpenSim.Region.CoreModules.World.Land
787 /// <returns>Land object at the point supplied</returns> 752 /// <returns>Land object at the point supplied</returns>
788 public ILandObject GetLandObject(float x_float, float y_float) 753 public ILandObject GetLandObject(float x_float, float y_float)
789 { 754 {
790 return GetLandObject((int)x_float, (int)y_float, true /* returnNullIfLandObjectNotFound */); 755 return GetLandObject((int)x_float, (int)y_float, true);
791 /* 756 }
792 int x;
793 int y;
794
795 if (x_float >= m_scene.RegionInfo.RegionSizeX || x_float < 0 || y_float >= m_scene.RegionInfo.RegionSizeX || y_float < 0)
796 return null;
797 757
798 try 758 // if x,y is off region this will return the parcel at cliped x,y
799 { 759 // as did code it replaces
800 x = Convert.ToInt32(Math.Floor(Convert.ToDouble(x_float) / (float)landUnit)); 760 public ILandObject GetLandObjectClipedXY(float x, float y)
801 y = Convert.ToInt32(Math.Floor(Convert.ToDouble(y_float) / (float)landUnit)); 761 {
802 } 762 //do clip inline
803 catch (OverflowException) 763 int avx = (int)x;
804 { 764 if (avx < 0)
805 return null; 765 avx = 0;
806 } 766 else if (avx >= m_scene.RegionInfo.RegionSizeX)
767 avx = (int)Constants.RegionSize - 1;
807 768
808 if (x >= (m_scene.RegionInfo.RegionSizeX / landUnit) 769 int avy = (int)y;
809 || y >= (m_scene.RegionInfo.RegionSizeY / landUnit) 770 if (avy < 0)
810 || x < 0 771 avy = 0;
811 || y < 0) 772 else if (avy >= m_scene.RegionInfo.RegionSizeY)
812 { 773 avy = (int)Constants.RegionSize - 1;
813 return null;
814 }
815 774
816 lock (m_landList) 775 lock (m_landIDList)
817 { 776 {
818 // Corner case. If an autoreturn happens during sim startup
819 // we will come here with the list uninitialized
820 //
821// int landId = m_landIDList[x, y];
822
823// if (landId == 0)
824// m_log.DebugFormat(
825// "[LAND MANAGEMENT MODULE]: No land object found at ({0}, {1}) on {2}",
826// x, y, m_scene.RegionInfo.RegionName);
827
828 try 777 try
829 { 778 {
830 if (m_landList.ContainsKey(m_landIDList[x, y])) 779 return m_landList[m_landIDList[avx / LandUnit, avy / LandUnit]];
831 return m_landList[m_landIDList[x, y]];
832 } 780 }
833 catch (Exception e) 781 catch (IndexOutOfRangeException)
834 { 782 {
835 m_log.DebugFormat("{0} GetLandObject exception. x={1}, y={2}, m_landIDList.len=({3},{4})", 783 return null;
836 LogHeader, x, y, m_landIDList.GetLength(0), m_landIDList.GetLength(1));
837 } 784 }
838
839 return null;
840 } 785 }
841 */
842 } 786 }
843 787
844 // Public entry. 788 // Public entry.
@@ -848,30 +792,28 @@ namespace OpenSim.Region.CoreModules.World.Land
848 return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */); 792 return GetLandObject(x, y, false /* returnNullIfLandObjectNotFound */);
849 } 793 }
850 794
851 /// <summary> 795 public ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds)
852 /// Given a region position, return the parcel land object for that location
853 /// </summary>
854 /// <returns>
855 /// The land object.
856 /// </returns>
857 /// <param name='x'></param>
858 /// <param name='y'></param>
859 /// <param name='returnNullIfLandObjectNotFound'>
860 /// Return null if the land object requested is not within the region's bounds.
861 /// </param>
862 private ILandObject GetLandObject(int x, int y, bool returnNullIfLandObjectOutsideBounds)
863 { 796 {
864 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0) 797 if (x >= m_scene.RegionInfo.RegionSizeX || y >= m_scene.RegionInfo.RegionSizeY || x < 0 || y < 0)
865 { 798 {
866 // These exceptions here will cause a lot of complaints from the users specifically because 799 // These exceptions here will cause a lot of complaints from the users specifically because
867 // they happen every time at border crossings 800 // they happen every time at border crossings
868 if (returnNullIfLandObjectOutsideBounds) 801 if (returnNullIfLandObjectOutsideBounds)
869 return null; 802 return null;
870 else 803 else
871 throw new Exception( 804 throw new Exception("Error: Parcel not found at point " + x + ", " + y);
872 String.Format("{0} GetLandObject for non-existent position. Region={1}, pos=<{2},{3}", 805 }
873 LogHeader, m_scene.RegionInfo.RegionName, x, y) 806
874 ); 807 lock (m_landIDList)
808 {
809 try
810 {
811 return m_landList[m_landIDList[x / 4, y / 4]];
812 }
813 catch (IndexOutOfRangeException)
814 {
815 return null;
816 }
875 } 817 }
876 818
877 return m_landList[m_landIDList[x / 4, y / 4]]; 819 return m_landList[m_landIDList[x / 4, y / 4]];
@@ -1033,7 +975,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1033 975
1034 //If we are still here, then they are subdividing within one piece of land 976 //If we are still here, then they are subdividing within one piece of land
1035 //Check owner 977 //Check owner
1036 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin)) 978 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin, true))
1037 { 979 {
1038 return; 980 return;
1039 } 981 }
@@ -1043,6 +985,8 @@ namespace OpenSim.Region.CoreModules.World.Land
1043 newLand.LandData.Name = newLand.LandData.Name; 985 newLand.LandData.Name = newLand.LandData.Name;
1044 newLand.LandData.GlobalID = UUID.Random(); 986 newLand.LandData.GlobalID = UUID.Random();
1045 newLand.LandData.Dwell = 0; 987 newLand.LandData.Dwell = 0;
988 // Clear "Show in search" on the cut out parcel to prevent double-charging
989 newLand.LandData.Flags &= ~(uint)ParcelFlags.ShowDirectory;
1046 990
1047 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); 991 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
1048 992
@@ -1058,11 +1002,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1058 //Now add the new land object 1002 //Now add the new land object
1059 ILandObject result = AddLandObject(newLand); 1003 ILandObject result = AddLandObject(newLand);
1060 1004
1061 if (result != null) 1005 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData);
1062 { 1006 result.SendLandUpdateToAvatarsOverMe();
1063 UpdateLandObject(startLandObject.LandData.LocalID, startLandObject.LandData); 1007 startLandObject.SendLandUpdateToAvatarsOverMe();
1064 result.SendLandUpdateToAvatarsOverMe(); 1008 m_scene.ForEachClient(SendParcelOverlay);
1065 } 1009
1066 } 1010 }
1067 1011
1068 /// <summary> 1012 /// <summary>
@@ -1104,7 +1048,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1104 { 1048 {
1105 return; 1049 return;
1106 } 1050 }
1107 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin)) 1051 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin, true))
1108 { 1052 {
1109 return; 1053 return;
1110 } 1054 }
@@ -1127,6 +1071,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1127 } 1071 }
1128 1072
1129 masterLandObject.SendLandUpdateToAvatarsOverMe(); 1073 masterLandObject.SendLandUpdateToAvatarsOverMe();
1074 m_scene.ForEachClient(SendParcelOverlay);
1130 } 1075 }
1131 1076
1132 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) 1077 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
@@ -1143,12 +1088,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1143 1088
1144 #region Parcel Updating 1089 #region Parcel Updating
1145 1090
1146 // Send parcel layer info for the whole region
1147 public void SendParcelOverlay(IClientAPI remote_client)
1148 {
1149 SendParcelOverlay(remote_client, 0, 0, (int)Constants.MaximumRegionSize);
1150 }
1151
1152 /// <summary> 1091 /// <summary>
1153 /// Send the parcel overlay blocks to the client. We send the overlay packets 1092 /// Send the parcel overlay blocks to the client. We send the overlay packets
1154 /// around a location and limited by the 'parcelLayerViewDistance'. This number 1093 /// around a location and limited by the 'parcelLayerViewDistance'. This number
@@ -1162,145 +1101,116 @@ namespace OpenSim.Region.CoreModules.World.Land
1162 /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param> 1101 /// <param name="xPlace">X position in the region to send surrounding parcel layer info</param>
1163 /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param> 1102 /// <param name="yPlace">y position in the region to send surrounding parcel layer info</param>
1164 /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param> 1103 /// <param name="layerViewDistance">Distance from x,y position to send parcel layer info</param>
1165 private void SendParcelOverlay(IClientAPI remote_client, int xPlace, int yPlace, int layerViewDistance) 1104 public void SendParcelOverlay(IClientAPI remote_client)
1166 { 1105 {
1106 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
1107 return;
1108
1167 const int LAND_BLOCKS_PER_PACKET = 1024; 1109 const int LAND_BLOCKS_PER_PACKET = 1024;
1168 1110
1169 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1111 byte[] byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1170 int byteArrayCount = 0; 1112 int byteArrayCount = 0;
1171 int sequenceID = 0; 1113 int sequenceID = 0;
1172 1114
1173 int xLow = 0; 1115 // Layer data is in LandUnit (4m) chunks
1174 int xHigh = (int)m_scene.RegionInfo.RegionSizeX; 1116 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY; y += LandUnit)
1175 int yLow = 0;
1176 int yHigh = (int)m_scene.RegionInfo.RegionSizeY;
1177
1178 if (shouldLimitParcelLayerInfoToViewDistance)
1179 { 1117 {
1180 // Compute view distance around the given point 1118 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX; x += LandUnit)
1181 int txLow = xPlace - layerViewDistance;
1182 int txHigh = xPlace + layerViewDistance;
1183 // If the distance is outside the region area, move the view distance to ba all in the region
1184 if (txLow < xLow)
1185 {
1186 txLow = xLow;
1187 txHigh = Math.Min(yLow + (layerViewDistance * 2), xHigh);
1188 }
1189 if (txHigh > xHigh)
1190 { 1119 {
1191 txLow = Math.Max(xLow, xHigh - (layerViewDistance * 2)); 1120 byte tempByte = 0; //This represents the byte for the current 4x4
1192 txHigh = xHigh;
1193 }
1194 xLow = txLow;
1195 xHigh = txHigh;
1196 1121
1197 int tyLow = yPlace - layerViewDistance; 1122 ILandObject currentParcelBlock = GetLandObject(x, y);
1198 int tyHigh = yPlace + layerViewDistance;
1199 if (tyLow < yLow)
1200 {
1201 tyLow = yLow;
1202 tyHigh = Math.Min(yLow + (layerViewDistance * 2), yHigh);
1203 }
1204 if (tyHigh > yHigh)
1205 {
1206 tyLow = Math.Max(yLow, yHigh - (layerViewDistance * 2));
1207 tyHigh = yHigh;
1208 }
1209 yLow = tyLow;
1210 yHigh = tyHigh;
1211 }
1212 // m_log.DebugFormat("{0} SendParcelOverlay: place=<{1},{2}>, vDist={3}, xLH=<{4},{5}, yLH=<{6},{7}>",
1213 // LogHeader, xPlace, yPlace, layerViewDistance, xLow, xHigh, yLow, yHigh);
1214 1123
1215 // Layer data is in landUnit (4m) chunks 1124 if (currentParcelBlock != null)
1216 for (int y = yLow; y < yHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
1217 {
1218 for (int x = xLow; x < xHigh / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
1219 {
1220 byteArray[byteArrayCount] = BuildLayerByte(GetLandObject(x * LandUnit, y * LandUnit), x, y, remote_client);
1221 byteArrayCount++;
1222 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1223 { 1125 {
1224 // m_log.DebugFormat("{0} SendParcelOverlay, sending packet, bytes={1}", LogHeader, byteArray.Length); 1126 // types
1225 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1127 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId)
1226 byteArrayCount = 0; 1128 {
1227 sequenceID++; 1129 //Owner Flag
1228 byteArray = new byte[LAND_BLOCKS_PER_PACKET]; 1130 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_REQUESTER;
1229 } 1131 }
1132 else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID))
1133 {
1134 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_GROUP;
1135 }
1136 else if (currentParcelBlock.LandData.SalePrice > 0 &&
1137 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1138 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1139 {
1140 //Sale type
1141 tempByte = (byte)LandChannel.LAND_TYPE_IS_FOR_SALE;
1142 }
1143 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1144 {
1145 //Public type
1146 tempByte = (byte)LandChannel.LAND_TYPE_PUBLIC; // this does nothing, its zero
1147 }
1148 // LAND_TYPE_IS_BEING_AUCTIONED still unsuported
1149 else
1150 {
1151 //Other Flag
1152 tempByte = (byte)LandChannel.LAND_TYPE_OWNED_BY_OTHER;
1153 }
1230 1154
1231 } 1155 // now flags
1232 } 1156 // border control
1233 1157
1234 if (byteArrayCount != 0) 1158 ILandObject westParcel = null;
1235 { 1159 ILandObject southParcel = null;
1236 remote_client.SendLandParcelOverlay(byteArray, sequenceID); 1160 if (x > 0)
1237 // m_log.DebugFormat("{0} SendParcelOverlay, complete sending packet, bytes={1}", LogHeader, byteArray.Length); 1161 {
1238 } 1162 westParcel = GetLandObject((x - 1), y);
1239 } 1163 }
1164 if (y > 0)
1165 {
1166 southParcel = GetLandObject(x, (y - 1));
1167 }
1240 1168
1241 private byte BuildLayerByte(ILandObject currentParcelBlock, int x, int y, IClientAPI remote_client) 1169 if (x == 0)
1242 { 1170 {
1243 byte tempByte = 0; //This represents the byte for the current 4x4 1171 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
1172 }
1173 else if (westParcel != null && westParcel != currentParcelBlock)
1174 {
1175 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST;
1176 }
1244 1177
1245 if (currentParcelBlock != null) 1178 if (y == 0)
1246 { 1179 {
1247 if (currentParcelBlock.LandData.OwnerID == remote_client.AgentId) 1180 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
1248 { 1181 }
1249 //Owner Flag 1182 else if (southParcel != null && southParcel != currentParcelBlock)
1250 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); 1183 {
1251 } 1184 tempByte |= (byte)LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH;
1252 else if (currentParcelBlock.LandData.SalePrice > 0 && 1185 }
1253 (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero ||
1254 currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId))
1255 {
1256 //Sale Flag
1257 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_IS_FOR_SALE);
1258 }
1259 else if (currentParcelBlock.LandData.OwnerID == UUID.Zero)
1260 {
1261 //Public Flag
1262 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_PUBLIC);
1263 }
1264 else
1265 {
1266 //Other Flag
1267 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_OTHER);
1268 }
1269 1186
1270 //Now for border control 1187 // local sound
1188 if ((currentParcelBlock.LandData.Flags & (uint)ParcelFlags.SoundLocal) != 0)
1189 tempByte |= (byte)LandChannel.LAND_FLAG_LOCALSOUND;
1271 1190
1272 ILandObject westParcel = null; 1191 // hide avatars
1273 ILandObject southParcel = null; 1192 if (!currentParcelBlock.LandData.SeeAVs)
1274 if (x > 0) 1193 tempByte |= (byte)LandChannel.LAND_FLAG_HIDEAVATARS;
1275 {
1276 westParcel = GetLandObject((x - 1) * LandUnit, y * LandUnit);
1277 }
1278 if (y > 0)
1279 {
1280 southParcel = GetLandObject(x * LandUnit, (y - 1) * LandUnit);
1281 }
1282 1194
1283 if (x == 0)
1284 {
1285 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1286 }
1287 else if (westParcel != null && westParcel != currentParcelBlock)
1288 {
1289 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_WEST);
1290 }
1291 1195
1292 if (y == 0) 1196 byteArray[byteArrayCount] = tempByte;
1293 { 1197 byteArrayCount++;
1294 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1198 if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
1295 } 1199 {
1296 else if (southParcel != null && southParcel != currentParcelBlock) 1200 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1297 { 1201 byteArrayCount = 0;
1298 tempByte = Convert.ToByte(tempByte | LandChannel.LAND_FLAG_PROPERTY_BORDER_SOUTH); 1202 sequenceID++;
1203 byteArray = new byte[LAND_BLOCKS_PER_PACKET];
1204 }
1205 }
1299 } 1206 }
1300 1207
1301 } 1208 }
1302 1209
1303 return tempByte; 1210 if (byteArrayCount > 0)
1211 {
1212 remote_client.SendLandParcelOverlay(byteArray, sequenceID);
1213 }
1304 } 1214 }
1305 1215
1306 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id, 1216 public void ClientOnParcelPropertiesRequest(int start_x, int start_y, int end_x, int end_y, int sequence_id,
@@ -1320,8 +1230,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1320 { 1230 {
1321 if (!temp.Contains(currentParcel)) 1231 if (!temp.Contains(currentParcel))
1322 { 1232 {
1323 currentParcel.ForceUpdateLandInfo(); 1233 if (!currentParcel.IsEitherBannedOrRestricted(remote_client.AgentId))
1324 temp.Add(currentParcel); 1234 {
1235 currentParcel.ForceUpdateLandInfo();
1236 temp.Add(currentParcel);
1237 }
1325 } 1238 }
1326 } 1239 }
1327 } 1240 }
@@ -1338,8 +1251,45 @@ namespace OpenSim.Region.CoreModules.World.Land
1338 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client); 1251 temp[i].SendLandProperties(sequence_id, snap_selection, requestResult, remote_client);
1339 } 1252 }
1340 1253
1341 // Also send the layer data around the point of interest 1254// SendParcelOverlay(remote_client);
1342 SendParcelOverlay(remote_client, (start_x + end_x) / 2, (start_y + end_y) / 2, parcelLayerViewDistance); 1255 }
1256
1257 public void UpdateLandProperties(ILandObject land, LandUpdateArgs args, IClientAPI remote_client)
1258 {
1259 bool snap_selection = false;
1260 bool needOverlay = false;
1261 if (land.UpdateLandProperties(args, remote_client, out snap_selection, out needOverlay))
1262 {
1263 //the proprieties to who changed them
1264 ScenePresence av = m_scene.GetScenePresence(remote_client.AgentId);
1265 if(av.IsChildAgent || land != GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y))
1266 land.SendLandProperties(-10000, false, LandChannel.LAND_RESULT_SINGLE, remote_client);
1267 else
1268 land.SendLandProperties(0, false, LandChannel.LAND_RESULT_SINGLE, remote_client);
1269
1270 UUID parcelID = land.LandData.GlobalID;
1271 m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
1272 {
1273 if (avatar.IsDeleted || avatar.isNPC)
1274 return;
1275
1276 IClientAPI client = avatar.ControllingClient;
1277 if (needOverlay)
1278 SendParcelOverlay(client);
1279
1280 if (avatar.IsChildAgent)
1281 return;
1282
1283 ILandObject aland = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
1284 if (aland != null)
1285 {
1286 if (client != remote_client && land == aland)
1287 aland.SendLandProperties(0, false, LandChannel.LAND_RESULT_SINGLE, client);
1288 }
1289 if (avatar.currentParcelUUID == parcelID)
1290 avatar.currentParcelUUID = parcelID; // force parcel flags review
1291 });
1292 }
1343 } 1293 }
1344 1294
1345 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client) 1295 public void ClientOnParcelPropertiesUpdateRequest(LandUpdateArgs args, int localID, IClientAPI remote_client)
@@ -1352,7 +1302,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1352 1302
1353 if (land != null) 1303 if (land != null)
1354 { 1304 {
1355 land.UpdateLandProperties(args, remote_client); 1305 UpdateLandProperties(land, args, remote_client);
1356 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client); 1306 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client);
1357 } 1307 }
1358 } 1308 }
@@ -1408,7 +1358,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1408 land.LandData.GroupID = UUID.Zero; 1358 land.LandData.GroupID = UUID.Zero;
1409 land.LandData.IsGroupOwned = false; 1359 land.LandData.IsGroupOwned = false;
1410 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1360 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1411
1412 m_scene.ForEachClient(SendParcelOverlay); 1361 m_scene.ForEachClient(SendParcelOverlay);
1413 land.SendLandUpdateToClient(true, remote_client); 1362 land.SendLandUpdateToClient(true, remote_client);
1414 UpdateLandObject(land.LandData.LocalID, land.LandData); 1363 UpdateLandObject(land.LandData.LocalID, land.LandData);
@@ -1459,7 +1408,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1459 land.LandData.SalePrice = 0; 1408 land.LandData.SalePrice = 0;
1460 land.LandData.AuthBuyerID = UUID.Zero; 1409 land.LandData.AuthBuyerID = UUID.Zero;
1461 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); 1410 land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
1462
1463 m_scene.ForEachClient(SendParcelOverlay); 1411 m_scene.ForEachClient(SendParcelOverlay);
1464 land.SendLandUpdateToClient(true, remote_client); 1412 land.SendLandUpdateToClient(true, remote_client);
1465 UpdateLandObject(land.LandData.LocalID, land.LandData); 1413 UpdateLandObject(land.LandData.LocalID, land.LandData);
@@ -1545,17 +1493,12 @@ namespace OpenSim.Region.CoreModules.World.Land
1545 1493
1546 private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1494 private void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1547 { 1495 {
1548// m_log.DebugFormat(
1549// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name);
1550
1551 // Prevent race conditions from any auto-creation of new parcels for varregions whilst we are still loading
1552 // the existing parcels.
1553 lock (m_landList) 1496 lock (m_landList)
1554 { 1497 {
1555 for (int i = 0; i < data.Count; i++) 1498 for (int i = 0; i < data.Count; i++)
1556 IncomingLandObjectFromStorage(data[i]); 1499 IncomingLandObjectFromStorage(data[i]);
1557 1500
1558 // Layer data is in landUnit (4m) chunks 1501 // Layer data is in LandUnit (4m) chunks
1559 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++) 1502 for (int y = 0; y < m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); y++)
1560 { 1503 {
1561 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++) 1504 for (int x = 0; x < m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize * (Constants.TerrainPatchSize / LandUnit); x++)
@@ -1565,7 +1508,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1565 if (m_landList.Count == 1) 1508 if (m_landList.Count == 1)
1566 { 1509 {
1567 m_log.DebugFormat( 1510 m_log.DebugFormat(
1568 "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}", 1511 "[{0}]: Auto-extending land parcel as landID at {1},{2} is 0 and only one land parcel is present in {3}",
1569 LogHeader, x, y, m_scene.Name); 1512 LogHeader, x, y, m_scene.Name);
1570 1513
1571 int onlyParcelID = 0; 1514 int onlyParcelID = 0;
@@ -1588,11 +1531,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1588 else if (m_landList.Count > 1) 1531 else if (m_landList.Count > 1)
1589 { 1532 {
1590 m_log.DebugFormat( 1533 m_log.DebugFormat(
1591 "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}", 1534 "{0}: Auto-creating land parcel as landID at {1},{2} is 0 and more than one land parcel is present in {3}",
1592 LogHeader, x, y, m_scene.Name); 1535 LogHeader, x, y, m_scene.Name);
1593 1536
1594 // There are several other parcels so we must create a new one for the unassigned space 1537 // There are several other parcels so we must create a new one for the unassigned space
1595 ILandObject newLand = new LandObject(UUID.Zero, false, m_scene); 1538 ILandObject newLand = new LandObject(UUID.Zero, false, m_scene);
1596 // Claim all the unclaimed "0" ids 1539 // Claim all the unclaimed "0" ids
1597 newLand.SetLandBitmap(CreateBitmapForID(0)); 1540 newLand.SetLandBitmap(CreateBitmapForID(0));
1598 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 1541 newLand.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
@@ -1603,7 +1546,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1603 { 1546 {
1604 // We should never reach this point as the separate code path when no land data exists should have fired instead. 1547 // We should never reach this point as the separate code path when no land data exists should have fired instead.
1605 m_log.WarnFormat( 1548 m_log.WarnFormat(
1606 "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present", 1549 "{0}: Ignoring request to auto-create parcel in {1} as there are no other parcels present",
1607 LogHeader, m_scene.Name); 1550 LogHeader, m_scene.Name);
1608 } 1551 }
1609 } 1552 }
@@ -1614,9 +1557,12 @@ namespace OpenSim.Region.CoreModules.World.Land
1614 1557
1615 private void IncomingLandObjectFromStorage(LandData data) 1558 private void IncomingLandObjectFromStorage(LandData data)
1616 { 1559 {
1617 ILandObject new_land = new LandObject(data, m_scene); 1560 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1561 new_land.LandData = data.Copy();
1562
1618 new_land.SetLandBitmapFromByteArray(); 1563 new_land.SetLandBitmapFromByteArray();
1619 AddLandObject(new_land); 1564 AddLandObject(new_land);
1565// new_land.SendLandUpdateToAvatarsOverMe();
1620 } 1566 }
1621 1567
1622 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 1568 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
@@ -1773,6 +1719,19 @@ namespace OpenSim.Region.CoreModules.World.Land
1773 land_update.ObscureMusic = properties.ObscureMusic; 1719 land_update.ObscureMusic = properties.ObscureMusic;
1774 land_update.ObscureMedia = properties.ObscureMedia; 1720 land_update.ObscureMedia = properties.ObscureMedia;
1775 1721
1722 if (args.ContainsKey("see_avs"))
1723 {
1724 land_update.SeeAVs = args["see_avs"].AsBoolean();
1725 land_update.AnyAVSounds = args["any_av_sounds"].AsBoolean();
1726 land_update.GroupAVSounds = args["group_av_sounds"].AsBoolean();
1727 }
1728 else
1729 {
1730 land_update.SeeAVs = true;
1731 land_update.AnyAVSounds = true;
1732 land_update.GroupAVSounds = true;
1733 }
1734
1776 ILandObject land; 1735 ILandObject land;
1777 lock (m_landList) 1736 lock (m_landList)
1778 { 1737 {
@@ -1781,13 +1740,14 @@ namespace OpenSim.Region.CoreModules.World.Land
1781 1740
1782 if (land != null) 1741 if (land != null)
1783 { 1742 {
1784 land.UpdateLandProperties(land_update, client); 1743 UpdateLandProperties(land,land_update, client);
1785 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client); 1744 m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client);
1786 } 1745 }
1787 else 1746 else
1788 { 1747 {
1789 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID); 1748 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID);
1790 } 1749 }
1750
1791 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1751 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
1792 } 1752 }
1793 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the 1753 // we cheat here: As we don't have (and want) a grid-global parcel-store, we can't return the
@@ -1940,14 +1900,93 @@ namespace OpenSim.Region.CoreModules.World.Land
1940 1900
1941 if (land == null) return; 1901 if (land == null) return;
1942 1902
1943 if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions)) 1903 if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions, false))
1944 return; 1904 return;
1945 1905
1946 land.LandData.OtherCleanTime = otherCleanTime; 1906 land.LandData.OtherCleanTime = otherCleanTime;
1947 1907
1948 UpdateLandObject(localID, land.LandData); 1908 UpdateLandObject(localID, land.LandData);
1949 } 1909 }
1950 1910
1911 public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID)
1912 {
1913 ILandObject land = null;
1914 List<ILandObject> Land = ((Scene)client.Scene).LandChannel.AllParcels();
1915 foreach (ILandObject landObject in Land)
1916 {
1917 if (landObject.LandData.LocalID == landID)
1918 {
1919 land = landObject;
1920 }
1921 }
1922 land.DeedToGroup(DefaultGodParcelGroup);
1923 land.LandData.Name = DefaultGodParcelName;
1924 land.SendLandUpdateToAvatarsOverMe();
1925 }
1926
1927 private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID)
1928 {
1929 ScenePresence SP;
1930 ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP);
1931 List<SceneObjectGroup> returns = new List<SceneObjectGroup>();
1932 if (SP.UserLevel != 0)
1933 {
1934 if (flags == 0) //All parcels, scripted or not
1935 {
1936 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1937 {
1938 if (e.OwnerID == targetID)
1939 {
1940 returns.Add(e);
1941 }
1942 }
1943 );
1944 }
1945 if (flags == 4) //All parcels, scripted object
1946 {
1947 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1948 {
1949 if (e.OwnerID == targetID)
1950 {
1951 if (e.ContainsScripts())
1952 {
1953 returns.Add(e);
1954 }
1955 }
1956 }
1957 );
1958 }
1959 if (flags == 4) //not target parcel, scripted object
1960 {
1961 ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e)
1962 {
1963 if (e.OwnerID == targetID)
1964 {
1965 ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y);
1966 if (landobject.LandData.OwnerID != e.OwnerID)
1967 {
1968 if (e.ContainsScripts())
1969 {
1970 returns.Add(e);
1971 }
1972 }
1973 }
1974 }
1975 );
1976 }
1977 foreach (SceneObjectGroup ol in returns)
1978 {
1979 ReturnObject(ol, client);
1980 }
1981 }
1982 }
1983 public void ReturnObject(SceneObjectGroup obj, IClientAPI client)
1984 {
1985 SceneObjectGroup[] objs = new SceneObjectGroup[1];
1986 objs[0] = obj;
1987 ((Scene)client.Scene).returnObjects(objs, client.AgentId);
1988 }
1989
1951 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>(); 1990 Dictionary<UUID, System.Threading.Timer> Timers = new Dictionary<UUID, System.Threading.Timer>();
1952 1991
1953 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) 1992 public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
@@ -1961,7 +2000,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1961 if (targetAvatar.UserLevel == 0) 2000 if (targetAvatar.UserLevel == 0)
1962 { 2001 {
1963 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 2002 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1964 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze)) 2003 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true))
1965 return; 2004 return;
1966 if (flags == 0) 2005 if (flags == 0)
1967 { 2006 {
@@ -1983,7 +2022,6 @@ namespace OpenSim.Region.CoreModules.World.Land
1983 } 2022 }
1984 } 2023 }
1985 } 2024 }
1986
1987 private void OnEndParcelFrozen(object avatar) 2025 private void OnEndParcelFrozen(object avatar)
1988 { 2026 {
1989 ScenePresence targetAvatar = (ScenePresence)avatar; 2027 ScenePresence targetAvatar = (ScenePresence)avatar;
@@ -1994,6 +2032,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1994 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false); 2032 targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false);
1995 } 2033 }
1996 2034
2035
1997 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) 2036 public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target)
1998 { 2037 {
1999 ScenePresence targetAvatar = null; 2038 ScenePresence targetAvatar = null;
@@ -2010,15 +2049,16 @@ namespace OpenSim.Region.CoreModules.World.Land
2010 2049
2011 // Check if you even have permission to do this 2050 // Check if you even have permission to do this
2012 ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 2051 ILandObject land = m_scene.LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
2013 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze) && 2052 if (!m_scene.Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze, true) &&
2014 !m_scene.Permissions.IsAdministrator(client.AgentId)) 2053 !m_scene.Permissions.IsAdministrator(client.AgentId))
2015 return; 2054 return;
2055
2016 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land); 2056 Vector3 pos = m_scene.GetNearestAllowedPosition(targetAvatar, land);
2017 2057
2018 targetAvatar.TeleportWithMomentum(pos, null); 2058 targetAvatar.TeleportWithMomentum(pos, null);
2019 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); 2059 targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname);
2020 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); 2060 parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected.");
2021 2061
2022 if ((flags & 1) != 0) // Ban TODO: Remove magic number 2062 if ((flags & 1) != 0) // Ban TODO: Remove magic number
2023 { 2063 {
2024 LandAccessEntry entry = new LandAccessEntry(); 2064 LandAccessEntry entry = new LandAccessEntry();
@@ -2171,37 +2211,50 @@ namespace OpenSim.Region.CoreModules.World.Land
2171 2211
2172 private void AppendParcelsSummaryReport(StringBuilder report) 2212 private void AppendParcelsSummaryReport(StringBuilder report)
2173 { 2213 {
2174 report.AppendFormat("Land information for {0}\n", m_scene.Name); 2214 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName);
2175 2215 report.AppendFormat(
2176 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 2216 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n",
2177 cdt.AddColumn("Parcel Name", ConsoleDisplayUtil.ParcelNameSize); 2217 "Parcel Name",
2178 cdt.AddColumn("ID", 3); 2218 "Local ID",
2179 cdt.AddColumn("Area", 6); 2219 "Area",
2180 cdt.AddColumn("Starts", ConsoleDisplayUtil.VectorSize); 2220 "AABBMin",
2181 cdt.AddColumn("Ends", ConsoleDisplayUtil.VectorSize); 2221 "AABBMax",
2182 cdt.AddColumn("Owner", ConsoleDisplayUtil.UserNameSize); 2222 "Owner");
2183 2223
2184 lock (m_landList) 2224 lock (m_landList)
2185 { 2225 {
2186 foreach (ILandObject lo in m_landList.Values) 2226 foreach (ILandObject lo in m_landList.Values)
2187 { 2227 {
2188 LandData ld = lo.LandData; 2228 LandData ld = lo.LandData;
2189 string ownerName; 2229
2190 if (ld.IsGroupOwned) 2230 report.AppendFormat(
2191 { 2231 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n",
2192 GroupRecord rec = m_groupManager.GetGroupRecord(ld.GroupID); 2232 ld.Name, ld.LocalID, ld.Area, ld.AABBMin, ld.AABBMax, m_userManager.GetUserName(ld.OwnerID));
2193 ownerName = (rec != null) ? rec.GroupName : "Unknown Group";
2194 }
2195 else
2196 {
2197 ownerName = m_userManager.GetUserName(ld.OwnerID);
2198 }
2199 cdt.AddRow(
2200 ld.Name, ld.LocalID, ld.Area, lo.StartPoint, lo.EndPoint, ownerName);
2201 } 2233 }
2202 } 2234 }
2235
2236 }
2237
2238 public void EnforceBans(ILandObject land, ScenePresence avatar)
2239 {
2240 if (avatar.AbsolutePosition.Z > LandChannel.BAN_LINE_SAFETY_HIEGHT)
2241 return;
2203 2242
2204 report.Append(cdt.ToString()); 2243 if (land.IsEitherBannedOrRestricted(avatar.UUID))
2244 {
2245 if (land.ContainsPoint(Convert.ToInt32(avatar.lastKnownAllowedPosition.X), Convert.ToInt32(avatar.lastKnownAllowedPosition.Y)))
2246 {
2247 Vector3? pos = m_scene.GetNearestAllowedPosition(avatar);
2248 if (pos == null)
2249 m_scene.TeleportClientHome(avatar.UUID, avatar.ControllingClient);
2250 else
2251 ForceAvatarToPosition(avatar, (Vector3)pos);
2252 }
2253 else
2254 {
2255 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
2256 }
2257 }
2205 } 2258 }
2206 2259
2207 private void AppendParcelReport(StringBuilder report, ILandObject lo) 2260 private void AppendParcelReport(StringBuilder report, ILandObject lo)
@@ -2214,8 +2267,6 @@ namespace OpenSim.Region.CoreModules.World.Land
2214 cdl.AddRow("Description", ld.Description); 2267 cdl.AddRow("Description", ld.Description);
2215 cdl.AddRow("Snapshot ID", ld.SnapshotID); 2268 cdl.AddRow("Snapshot ID", ld.SnapshotID);
2216 cdl.AddRow("Area", ld.Area); 2269 cdl.AddRow("Area", ld.Area);
2217 cdl.AddRow("Starts", lo.StartPoint);
2218 cdl.AddRow("Ends", lo.EndPoint);
2219 cdl.AddRow("AABB Min", ld.AABBMin); 2270 cdl.AddRow("AABB Min", ld.AABBMin);
2220 cdl.AddRow("AABB Max", ld.AABBMax); 2271 cdl.AddRow("AABB Max", ld.AABBMax);
2221 string ownerName; 2272 string ownerName;
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index a0c1b9d..040c90b 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -50,7 +50,8 @@ namespace OpenSim.Region.CoreModules.World.Land
50 private readonly int landUnit = 4; 50 private readonly int landUnit = 4;
51 51
52 private int m_lastSeqId = 0; 52 private int m_lastSeqId = 0;
53 53 private int m_expiryCounter = 0;
54
54 protected Scene m_scene; 55 protected Scene m_scene;
55 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>(); 56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
56 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>(); 57 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
@@ -58,7 +59,12 @@ namespace OpenSim.Region.CoreModules.World.Land
58 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>(); 59 protected ExpiringCache<UUID, bool> m_groupMemberCache = new ExpiringCache<UUID, bool>();
59 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds 60 protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds
60 61
61 public bool[,] LandBitmap { get; set; } 62 private bool[,] m_landBitmap;
63 public bool[,] LandBitmap
64 {
65 get { return m_landBitmap; }
66 set { m_landBitmap = value; }
67 }
62 68
63 #endregion 69 #endregion
64 70
@@ -69,7 +75,13 @@ namespace OpenSim.Region.CoreModules.World.Land
69 return free; 75 return free;
70 } 76 }
71 77
72 public LandData LandData { get; set; } 78 protected LandData m_landData;
79 public LandData LandData
80 {
81 get { return m_landData; }
82
83 set { m_landData = value; }
84 }
73 85
74 public IPrimCounts PrimCounts { get; set; } 86 public IPrimCounts PrimCounts { get; set; }
75 87
@@ -141,6 +153,8 @@ namespace OpenSim.Region.CoreModules.World.Land
141 else 153 else
142 LandData.GroupID = UUID.Zero; 154 LandData.GroupID = UUID.Zero;
143 LandData.IsGroupOwned = is_group_owned; 155 LandData.IsGroupOwned = is_group_owned;
156
157 m_scene.EventManager.OnFrame += OnFrame;
144 } 158 }
145 159
146 #endregion 160 #endregion
@@ -195,10 +209,27 @@ namespace OpenSim.Region.CoreModules.World.Land
195 else 209 else
196 { 210 {
197 // Normal Calculations 211 // Normal Calculations
198 int parcelMax = (int)(((float)LandData.Area / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 212 int parcelMax = (int)( (long)LandData.Area
199 * (float)m_scene.RegionInfo.ObjectCapacity 213 * (long)m_scene.RegionInfo.ObjectCapacity
200 * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 214 * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus
201 // TODO: The calculation of ObjectBonus should be refactored. It does still not work in the same manner as SL! 215 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
216 //m_log.DebugFormat("Area: {0}, Capacity {1}, Bonus {2}, Parcel {3}", LandData.Area, m_scene.RegionInfo.ObjectCapacity, m_scene.RegionInfo.RegionSettings.ObjectBonus, parcelMax);
217 return parcelMax;
218 }
219 }
220
221 private int GetParcelBasePrimCount()
222 {
223 if (overrideParcelMaxPrimCount != null)
224 {
225 return overrideParcelMaxPrimCount(this);
226 }
227 else
228 {
229 // Normal Calculations
230 int parcelMax = (int)((long)LandData.Area
231 * (long)m_scene.RegionInfo.ObjectCapacity
232 / 65536L);
202 return parcelMax; 233 return parcelMax;
203 } 234 }
204 } 235 }
@@ -212,8 +243,10 @@ namespace OpenSim.Region.CoreModules.World.Land
212 else 243 else
213 { 244 {
214 //Normal Calculations 245 //Normal Calculations
215 int simMax = (int)(((float)LandData.SimwideArea / (m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY)) 246 int simMax = (int)( (long)LandData.SimwideArea
216 * (float)m_scene.RegionInfo.ObjectCapacity); 247 * (long)m_scene.RegionInfo.ObjectCapacity
248 / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) );
249 // m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}", LandData.SimwideArea, m_scene.RegionInfo.ObjectCapacity, simMax);
217 return simMax; 250 return simMax;
218 } 251 }
219 } 252 }
@@ -224,6 +257,9 @@ namespace OpenSim.Region.CoreModules.World.Land
224 257
225 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) 258 public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client)
226 { 259 {
260 if (remote_client.SceneAgent.PresenceType == PresenceType.Npc)
261 return;
262
227 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 263 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
228 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); 264 // uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome));
229 uint regionFlags = (uint)(RegionFlags.PublicAllowed 265 uint regionFlags = (uint)(RegionFlags.PublicAllowed
@@ -248,14 +284,15 @@ namespace OpenSim.Region.CoreModules.World.Land
248 remote_client.SendLandProperties(seq_id, 284 remote_client.SendLandProperties(seq_id,
249 snap_selection, request_result, this, 285 snap_selection, request_result, this,
250 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, 286 (float)m_scene.RegionInfo.RegionSettings.ObjectBonus,
251 GetParcelMaxPrimCount(), 287 GetParcelBasePrimCount(),
252 GetSimulatorMaxPrimCount(), regionFlags); 288 GetSimulatorMaxPrimCount(), regionFlags);
253 } 289 }
254 290
255 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) 291 public bool UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client, out bool snap_selection, out bool needOverlay)
256 { 292 {
257 //Needs later group support 293 //Needs later group support
258 bool snap_selection = false; 294 snap_selection = false;
295 needOverlay = false;
259 LandData newData = LandData.Copy(); 296 LandData newData = LandData.Copy();
260 297
261 uint allowedDelta = 0; 298 uint allowedDelta = 0;
@@ -264,7 +301,7 @@ namespace OpenSim.Region.CoreModules.World.Land
264 // ParcelFlags.ForSaleObjects 301 // ParcelFlags.ForSaleObjects
265 // ParcelFlags.LindenHome 302 // ParcelFlags.LindenHome
266 303
267 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 304 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, false))
268 { 305 {
269 allowedDelta |= (uint)(ParcelFlags.AllowLandmark | 306 allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
270 ParcelFlags.AllowTerraform | 307 ParcelFlags.AllowTerraform |
@@ -277,9 +314,12 @@ namespace OpenSim.Region.CoreModules.World.Land
277 ParcelFlags.AllowAPrimitiveEntry | 314 ParcelFlags.AllowAPrimitiveEntry |
278 ParcelFlags.AllowGroupObjectEntry | 315 ParcelFlags.AllowGroupObjectEntry |
279 ParcelFlags.AllowFly); 316 ParcelFlags.AllowFly);
317 newData.SeeAVs = args.SeeAVs;
318 newData.AnyAVSounds = args.AnyAVSounds;
319 newData.GroupAVSounds = args.GroupAVSounds;
280 } 320 }
281 321
282 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale)) 322 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale, true))
283 { 323 {
284 if (args.AuthBuyerID != newData.AuthBuyerID || 324 if (args.AuthBuyerID != newData.AuthBuyerID ||
285 args.SalePrice != newData.SalePrice) 325 args.SalePrice != newData.SalePrice)
@@ -302,30 +342,30 @@ namespace OpenSim.Region.CoreModules.World.Land
302 allowedDelta |= (uint)ParcelFlags.ForSale; 342 allowedDelta |= (uint)ParcelFlags.ForSale;
303 } 343 }
304 344
305 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces)) 345 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces, false))
306 { 346 {
307 newData.Category = args.Category; 347 newData.Category = args.Category;
308 348
309 allowedDelta |= (uint)(ParcelFlags.ShowDirectory | 349 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
310 ParcelFlags.AllowPublish | 350 ParcelFlags.AllowPublish |
311 ParcelFlags.MaturePublish); 351 ParcelFlags.MaturePublish) | (uint)(1 << 23);
312 } 352 }
313 353
314 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity)) 354 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity, false))
315 { 355 {
316 newData.Description = args.Desc; 356 newData.Description = args.Desc;
317 newData.Name = args.Name; 357 newData.Name = args.Name;
318 newData.SnapshotID = args.SnapshotID; 358 newData.SnapshotID = args.SnapshotID;
319 } 359 }
320 360
321 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint)) 361 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint, false))
322 { 362 {
323 newData.LandingType = args.LandingType; 363 newData.LandingType = args.LandingType;
324 newData.UserLocation = args.UserLocation; 364 newData.UserLocation = args.UserLocation;
325 newData.UserLookAt = args.UserLookAt; 365 newData.UserLookAt = args.UserLookAt;
326 } 366 }
327 367
328 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia)) 368 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia, false))
329 { 369 {
330 newData.MediaAutoScale = args.MediaAutoScale; 370 newData.MediaAutoScale = args.MediaAutoScale;
331 newData.MediaID = args.MediaID; 371 newData.MediaID = args.MediaID;
@@ -346,7 +386,7 @@ namespace OpenSim.Region.CoreModules.World.Land
346 ParcelFlags.UseEstateVoiceChan); 386 ParcelFlags.UseEstateVoiceChan);
347 } 387 }
348 388
349 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses)) 389 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false))
350 { 390 {
351 newData.PassHours = args.PassHours; 391 newData.PassHours = args.PassHours;
352 newData.PassPrice = args.PassPrice; 392 newData.PassPrice = args.PassPrice;
@@ -354,13 +394,13 @@ namespace OpenSim.Region.CoreModules.World.Land
354 allowedDelta |= (uint)ParcelFlags.UsePassList; 394 allowedDelta |= (uint)ParcelFlags.UsePassList;
355 } 395 }
356 396
357 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed)) 397 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed, false))
358 { 398 {
359 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup | 399 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
360 ParcelFlags.UseAccessList); 400 ParcelFlags.UseAccessList);
361 } 401 }
362 402
363 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned)) 403 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned, false))
364 { 404 {
365 allowedDelta |= (uint)(ParcelFlags.UseBanList | 405 allowedDelta |= (uint)(ParcelFlags.UseBanList |
366 ParcelFlags.DenyAnonymous | 406 ParcelFlags.DenyAnonymous |
@@ -372,9 +412,16 @@ namespace OpenSim.Region.CoreModules.World.Land
372 uint preserve = LandData.Flags & ~allowedDelta; 412 uint preserve = LandData.Flags & ~allowedDelta;
373 newData.Flags = preserve | (args.ParcelFlags & allowedDelta); 413 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
374 414
415 uint curdelta = LandData.Flags ^ newData.Flags;
416 curdelta &= (uint)(ParcelFlags.SoundLocal);
417
418 if(curdelta != 0 || newData.SeeAVs != LandData.SeeAVs)
419 needOverlay = true;
420
375 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 421 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
376 SendLandUpdateToAvatarsOverMe(snap_selection); 422 return true;
377 } 423 }
424 return false;
378 } 425 }
379 426
380 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) 427 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
@@ -395,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Land
395 UUID previousOwner = LandData.OwnerID; 442 UUID previousOwner = LandData.OwnerID;
396 443
397 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 444 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
398 m_scene.EventManager.TriggerParcelPrimCountUpdate(); 445// m_scene.EventManager.TriggerParcelPrimCountUpdate();
399 SendLandUpdateToAvatarsOverMe(true); 446 SendLandUpdateToAvatarsOverMe(true);
400 447
401 if (sellObjects) SellLandObjects(previousOwner); 448 if (sellObjects) SellLandObjects(previousOwner);
@@ -568,6 +615,7 @@ namespace OpenSim.Region.CoreModules.World.Land
568 615
569 public void SendLandUpdateToAvatarsOverMe(bool snap_selection) 616 public void SendLandUpdateToAvatarsOverMe(bool snap_selection)
570 { 617 {
618 m_scene.EventManager.TriggerParcelPrimCountUpdate();
571 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar) 619 m_scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
572 { 620 {
573 ILandObject over = null; 621 ILandObject over = null;
@@ -594,6 +642,7 @@ namespace OpenSim.Region.CoreModules.World.Land
594 avatar.Invulnerable = true; 642 avatar.Invulnerable = true;
595 643
596 SendLandUpdateToClient(snap_selection, avatar.ControllingClient); 644 SendLandUpdateToClient(snap_selection, avatar.ControllingClient);
645 avatar.currentParcelUUID = LandData.GlobalID;
597 } 646 }
598 } 647 }
599 }); 648 });
@@ -722,10 +771,11 @@ namespace OpenSim.Region.CoreModules.World.Land
722 /// </summary> 771 /// </summary>
723 private void UpdateAABBAndAreaValues() 772 private void UpdateAABBAndAreaValues()
724 { 773 {
725 int min_x = 10000; 774
726 int min_y = 10000; 775 int min_x = Int32.MaxValue;
727 int max_x = 0; 776 int min_y = Int32.MaxValue;
728 int max_y = 0; 777 int max_x = Int32.MinValue;
778 int max_y = Int32.MinValue;
729 int tempArea = 0; 779 int tempArea = 0;
730 int x, y; 780 int x, y;
731 for (x = 0; x < LandBitmap.GetLength(0); x++) 781 for (x = 0; x < LandBitmap.GetLength(0); x++)
@@ -734,10 +784,14 @@ namespace OpenSim.Region.CoreModules.World.Land
734 { 784 {
735 if (LandBitmap[x, y] == true) 785 if (LandBitmap[x, y] == true)
736 { 786 {
737 if (min_x > x) min_x = x; 787 if (min_x > x)
738 if (min_y > y) min_y = y; 788 min_x = x;
739 if (max_x < x) max_x = x; 789 if (min_y > y)
740 if (max_y < y) max_y = y; 790 min_y = y;
791 if (max_x < x)
792 max_x = x;
793 if (max_y < y)
794 max_y = y;
741 tempArea += landUnit * landUnit; //16sqm peice of land 795 tempArea += landUnit * landUnit; //16sqm peice of land
742 } 796 }
743 } 797 }
@@ -745,24 +799,42 @@ namespace OpenSim.Region.CoreModules.World.Land
745 int tx = min_x * landUnit; 799 int tx = min_x * landUnit;
746 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 800 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1))
747 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 801 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1);
802 int htx;
803 if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
804 htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
805 else
806 htx = tx;
807
748 int ty = min_y * landUnit; 808 int ty = min_y * landUnit;
749 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 809 int hty;
750 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 810
811 if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
812 hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
813 else
814 hty = ty;
751 815
752 LandData.AABBMin = 816 LandData.AABBMin =
753 new Vector3( 817 new Vector3(
754 (float)(min_x * landUnit), (float)(min_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 818 (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
755 819
820 max_x++;
756 tx = max_x * landUnit; 821 tx = max_x * landUnit;
757 if (tx > ((int)m_scene.RegionInfo.RegionSizeX - 1)) 822 if (tx >= ((int)m_scene.RegionInfo.RegionSizeX))
758 tx = ((int)m_scene.RegionInfo.RegionSizeX - 1); 823 htx = (int)m_scene.RegionInfo.RegionSizeX - 1;
759 ty = max_y * landUnit; 824 else
760 if (ty > ((int)m_scene.RegionInfo.RegionSizeY - 1)) 825 htx = tx;
761 ty = ((int)m_scene.RegionInfo.RegionSizeY - 1); 826
827 max_y++;
828 ty = max_y * 4;
829
830 if (ty >= ((int)m_scene.RegionInfo.RegionSizeY))
831 hty = (int)m_scene.RegionInfo.RegionSizeY - 1;
832 else
833 hty = ty;
762 834
763 LandData.AABBMax 835 LandData.AABBMax
764 = new Vector3( 836 = new Vector3(
765 (float)(max_x * landUnit), (float)(max_y * landUnit), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0); 837 (float)(tx), (float)(ty), m_scene != null ? (float)m_scene.Heightmap[htx, hty] : 0);
766 838
767 LandData.Area = tempArea; 839 LandData.Area = tempArea;
768 } 840 }
@@ -778,7 +850,6 @@ namespace OpenSim.Region.CoreModules.World.Land
778 public void SetLandBitmap(bool[,] bitmap) 850 public void SetLandBitmap(bool[,] bitmap)
779 { 851 {
780 LandBitmap = bitmap; 852 LandBitmap = bitmap;
781 // m_log.DebugFormat("{0} SetLandBitmap. BitmapSize=<{1},{2}>", LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
782 ForceUpdateLandInfo(); 853 ForceUpdateLandInfo();
783 } 854 }
784 855
@@ -879,13 +950,32 @@ namespace OpenSim.Region.CoreModules.World.Land
879 private byte[] ConvertLandBitmapToBytes() 950 private byte[] ConvertLandBitmapToBytes()
880 { 951 {
881 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8]; 952 byte[] tempConvertArr = new byte[LandBitmap.GetLength(0) * LandBitmap.GetLength(1) / 8];
882 byte tempByte = 0; 953
883 int byteNum = 0; 954 int tempByte = 0;
884 int i = 0; 955 int i, byteNum = 0;
956 int mask = 1;
957 i = 0;
885 for (int y = 0; y < LandBitmap.GetLength(1); y++) 958 for (int y = 0; y < LandBitmap.GetLength(1); y++)
886 { 959 {
887 for (int x = 0; x < LandBitmap.GetLength(0); x++) 960 for (int x = 0; x < LandBitmap.GetLength(0); x++)
888 { 961 {
962 if (LandBitmap[x, y])
963 tempByte |= mask;
964 mask = mask << 1;
965 if (mask == 0x100)
966 {
967 mask = 1;
968 tempConvertArr[byteNum++] = (byte)tempByte;
969 tempByte = 0;
970 }
971 }
972 }
973
974 if(tempByte != 0 && byteNum < 512)
975 tempConvertArr[byteNum] = (byte)tempByte;
976
977
978/*
889 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); 979 tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8));
890 if (i % 8 == 0) 980 if (i % 8 == 0)
891 { 981 {
@@ -894,10 +984,13 @@ namespace OpenSim.Region.CoreModules.World.Land
894 i = 0; 984 i = 0;
895 byteNum++; 985 byteNum++;
896 } 986 }
987<<<<<<< HEAD
897 } 988 }
898 } 989 }
899 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>", 990 // m_log.DebugFormat("{0} ConvertLandBitmapToBytes. BitmapSize=<{1},{2}>",
900 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1)); 991 // LogHeader, LandBitmap.GetLength(0), LandBitmap.GetLength(1));
992=======
993 */
901 return tempConvertArr; 994 return tempConvertArr;
902 } 995 }
903 996
@@ -951,7 +1044,7 @@ namespace OpenSim.Region.CoreModules.World.Land
951 1044
952 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client) 1045 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
953 { 1046 {
954 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1047 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
955 { 1048 {
956 List<uint> resultLocalIDs = new List<uint>(); 1049 List<uint> resultLocalIDs = new List<uint>();
957 try 1050 try
@@ -1001,7 +1094,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1001 /// </param> 1094 /// </param>
1002 public void SendLandObjectOwners(IClientAPI remote_client) 1095 public void SendLandObjectOwners(IClientAPI remote_client)
1003 { 1096 {
1004 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions)) 1097 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions, true))
1005 { 1098 {
1006 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>(); 1099 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
1007 List<UUID> groups = new List<UUID>(); 1100 List<UUID> groups = new List<UUID>();
@@ -1233,6 +1326,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1233 public void SetMediaUrl(string url) 1326 public void SetMediaUrl(string url)
1234 { 1327 {
1235 LandData.MediaURL = url; 1328 LandData.MediaURL = url;
1329 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1236 SendLandUpdateToAvatarsOverMe(); 1330 SendLandUpdateToAvatarsOverMe();
1237 } 1331 }
1238 1332
@@ -1243,6 +1337,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1243 public void SetMusicUrl(string url) 1337 public void SetMusicUrl(string url)
1244 { 1338 {
1245 LandData.MusicURL = url; 1339 LandData.MusicURL = url;
1340 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, LandData);
1246 SendLandUpdateToAvatarsOverMe(); 1341 SendLandUpdateToAvatarsOverMe();
1247 } 1342 }
1248 1343
@@ -1257,6 +1352,17 @@ namespace OpenSim.Region.CoreModules.World.Land
1257 1352
1258 #endregion 1353 #endregion
1259 1354
1355 private void OnFrame()
1356 {
1357 m_expiryCounter++;
1358
1359 if (m_expiryCounter >= 50)
1360 {
1361 ExpireAccessList();
1362 m_expiryCounter = 0;
1363 }
1364 }
1365
1260 private void ExpireAccessList() 1366 private void ExpireAccessList()
1261 { 1367 {
1262 List<LandAccessEntry> delete = new List<LandAccessEntry>(); 1368 List<LandAccessEntry> delete = new List<LandAccessEntry>();
@@ -1267,7 +1373,22 @@ namespace OpenSim.Region.CoreModules.World.Land
1267 delete.Add(entry); 1373 delete.Add(entry);
1268 } 1374 }
1269 foreach (LandAccessEntry entry in delete) 1375 foreach (LandAccessEntry entry in delete)
1376 {
1270 LandData.ParcelAccessList.Remove(entry); 1377 LandData.ParcelAccessList.Remove(entry);
1378 ScenePresence presence;
1379
1380 if (m_scene.TryGetScenePresence(entry.AgentID, out presence) && (!presence.IsChildAgent))
1381 {
1382 ILandObject land = m_scene.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y);
1383 if (land.LandData.LocalID == LandData.LocalID)
1384 {
1385 Vector3 pos = m_scene.GetNearestAllowedPosition(presence, land);
1386 presence.TeleportWithMomentum(pos, null);
1387 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
1388 }
1389 }
1390 m_log.DebugFormat("[LAND]: Removing entry {0} because it has expired", entry.AgentID);
1391 }
1271 1392
1272 if (delete.Count > 0) 1393 if (delete.Count > 0)
1273 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this); 1394 m_scene.EventManager.TriggerLandObjectUpdated((uint)LandData.LocalID, this);
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index 9b51cc8..771fdd2 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -207,7 +207,7 @@ namespace OpenSim.Region.CoreModules.World.Land
207 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) 207 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
208 { 208 {
209 UUID landOwner = landData.OwnerID; 209 UUID landOwner = landData.OwnerID;
210 int partCount = obj.Parts.Length; 210 int partCount = obj.GetPartCount();
211 211
212 m_SimwideCounts[landOwner] += partCount; 212 m_SimwideCounts[landOwner] += partCount;
213 if (parcelCounts.Users.ContainsKey(obj.OwnerID)) 213 if (parcelCounts.Users.ContainsKey(obj.OwnerID))
@@ -597,4 +597,4 @@ namespace OpenSim.Region.CoreModules.World.Land
597 } 597 }
598 } 598 }
599 } 599 }
600} \ No newline at end of file 600}
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 796a15f..5155804 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -112,7 +112,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
112 //} 112 //}
113 //t = System.Environment.TickCount - t; 113 //t = System.Environment.TickCount - t;
114 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); 114 //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t);
115
116 if (drawPrimVolume) 115 if (drawPrimVolume)
117 { 116 {
118 DrawObjectVolume(m_scene, mapbmp); 117 DrawObjectVolume(m_scene, mapbmp);
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index 9f23141..0ec2053 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
288 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height) 288 if (mapbmp.Width != hm.Width || mapbmp.Height != hm.Height)
289 { 289 {
290 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>", 290 m_log.ErrorFormat("{0} TerrainToBitmap. Passed bitmap wrong dimensions. passed=<{1},{2}>, size=<{3},{4}>",
291 LogHeader, mapbmp.Width, mapbmp.Height, hm.Width, hm.Height); 291 "[TEXTURED MAP TILE RENDERER]", mapbmp.Width, mapbmp.Height, hm.Width, hm.Height);
292 } 292 }
293 293
294 // These textures should be in the AssetCache anyway, as every client conneting to this 294 // These textures should be in the AssetCache anyway, as every client conneting to this
@@ -371,8 +371,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
371 // first, rescale h to 0.0 - 1.0 371 // first, rescale h to 0.0 - 1.0
372 hmod = (hmod - low) / (high - low); 372 hmod = (hmod - low) / (high - low);
373 // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4 373 // now we have to split: 0.00 => color1, 0.33 => color2, 0.67 => color3, 1.00 => color4
374 if (hmod < 1f/3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f); 374 if (hmod < 1f / 3f) hsv = interpolateHSV(ref hsv1, ref hsv2, hmod * 3f);
375 else if (hmod < 2f/3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f); 375 else if (hmod < 2f / 3f) hsv = interpolateHSV(ref hsv2, ref hsv3, (hmod * 3f) - 1f);
376 else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f); 376 else hsv = interpolateHSV(ref hsv3, ref hsv4, (hmod * 3f) - 2f);
377 } 377 }
378 378
diff --git a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
index 0a4e83e..f13d648 100644
--- a/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
+++ b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
@@ -190,6 +190,9 @@ namespace OpenSim.Region.CoreModules.World.LightShare
190 190
191 public void SendProfileToClient(IClientAPI client, RegionLightShareData wl) 191 public void SendProfileToClient(IClientAPI client, RegionLightShareData wl)
192 { 192 {
193 if (client == null)
194 return;
195
193 if (m_enableWindlight) 196 if (m_enableWindlight)
194 { 197 {
195 if (m_scene.RegionInfo.WindlightSettings.valid) 198 if (m_scene.RegionInfo.WindlightSettings.valid)
@@ -207,8 +210,8 @@ namespace OpenSim.Region.CoreModules.World.LightShare
207 210
208 private void EventManager_OnMakeRootAgent(ScenePresence presence) 211 private void EventManager_OnMakeRootAgent(ScenePresence presence)
209 { 212 {
210// m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client {0}", presence.Name); 213 if (m_enableWindlight && m_scene.RegionInfo.WindlightSettings.valid)
211 214 m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client");
212 SendProfileToClient(presence.ControllingClient); 215 SendProfileToClient(presence.ControllingClient);
213 } 216 }
214 217
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 2abc910..0e0f05f 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -173,6 +173,13 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
173 return false; 173 return false;
174 } 174 }
175 175
176 if ((perms & (uint)PermissionMask.Copy) == 0)
177 {
178 if (m_dialogModule != null)
179 m_dialogModule.SendAlertToUser(remoteClient, "This sale has been blocked by the permissions system");
180 return false;
181 }
182
176 AssetBase asset = m_scene.CreateAsset( 183 AssetBase asset = m_scene.CreateAsset(
177 group.GetPartName(localID), 184 group.GetPartName(localID),
178 group.GetPartDescription(localID), 185 group.GetPartDescription(localID),
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 780ec69..765c1f2 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -43,8 +43,8 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
43 43
44namespace OpenSim.Region.CoreModules.World.Permissions 44namespace OpenSim.Region.CoreModules.World.Permissions
45{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PermissionsModule")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultPermissionsModule")]
47 public class PermissionsModule : INonSharedRegionModule, IPermissionsModule 47 public class DefaultPermissionsModule : INonSharedRegionModule, IPermissionsModule
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
@@ -349,7 +349,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
349 349
350 public string Name 350 public string Name
351 { 351 {
352 get { return "PermissionsModule"; } 352 get { return "DefaultPermissionsModule"; }
353 } 353 }
354 354
355 public Type ReplaceableInterface 355 public Type ReplaceableInterface
@@ -705,7 +705,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
705 if (user == objectOwner) 705 if (user == objectOwner)
706 return PermissionClass.Owner; 706 return PermissionClass.Owner;
707 707
708 if (IsFriendWithPerms(user, objectOwner)) 708 if (IsFriendWithPerms(user, objectOwner) && !obj.ParentGroup.IsAttachment)
709 return PermissionClass.Owner; 709 return PermissionClass.Owner;
710 710
711 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set 711 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
@@ -1052,7 +1052,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1052 return GenericObjectPermission(editorID, objectID, false); 1052 return GenericObjectPermission(editorID, objectID, false);
1053 } 1053 }
1054 1054
1055 private bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, Scene scene) 1055 private bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, Scene scene, bool allowManager)
1056 { 1056 {
1057 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 1057 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1058 if (m_bypassPermissions) return m_bypassPermissionsValue; 1058 if (m_bypassPermissions) return m_bypassPermissionsValue;
diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
index bb4dcce..b9bcb8b 100644
--- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
@@ -271,8 +271,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
271 float totalFrameTime = stats[8]; 271 float totalFrameTime = stats[8];
272// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator 272// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator
273 float physicsFrameTime = stats[10]; 273 float physicsFrameTime = stats[10];
274 float otherFrameTime = stats[11]; 274 float otherFrameTime = stats[12];
275// float imageFrameTime = stats.StatsBlock[12].StatValue; // Ignored 275// float imageFrameTime = stats.StatsBlock[11].StatValue; // Ignored
276 float inPacketsPerSecond = stats[13]; 276 float inPacketsPerSecond = stats[13];
277 float outPacketsPerSecond = stats[14]; 277 float outPacketsPerSecond = stats[14];
278 float unackedBytes = stats[15]; 278 float unackedBytes = stats[15];
@@ -280,7 +280,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
280 float pendingDownloads = stats[17]; 280 float pendingDownloads = stats[17];
281 float pendingUploads = stats[18]; 281 float pendingUploads = stats[18];
282 float activeScripts = stats[19]; 282 float activeScripts = stats[19];
283 float scriptLinesPerSecond = stats[20]; 283 float scriptLinesPerSecond = stats[23];
284 284
285 StringBuilder sb = new StringBuilder(); 285 StringBuilder sb = new StringBuilder();
286 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName); 286 sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 75a8295..e6a0205 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -29,6 +29,8 @@ using System;
29using System.Linq; 29using System.Linq;
30using System.Reflection; 30using System.Reflection;
31using System.Timers; 31using System.Timers;
32using System.IO;
33using System.Diagnostics;
32using System.Threading; 34using System.Threading;
33using System.Collections.Generic; 35using System.Collections.Generic;
34using log4net; 36using log4net;
@@ -57,13 +59,24 @@ namespace OpenSim.Region.CoreModules.World.Region
57 protected UUID m_Initiator; 59 protected UUID m_Initiator;
58 protected bool m_Notice = false; 60 protected bool m_Notice = false;
59 protected IDialogModule m_DialogModule = null; 61 protected IDialogModule m_DialogModule = null;
62 protected string m_MarkerPath = String.Empty;
63 private int[] m_CurrentAlerts = null;
60 64
61 public void Initialise(IConfigSource config) 65 public void Initialise(IConfigSource config)
62 { 66 {
67 IConfig restartConfig = config.Configs["RestartModule"];
68 if (restartConfig != null)
69 {
70 m_MarkerPath = restartConfig.GetString("MarkerPath", String.Empty);
71 }
63 } 72 }
64 73
65 public void AddRegion(Scene scene) 74 public void AddRegion(Scene scene)
66 { 75 {
76 if (m_MarkerPath != String.Empty)
77 File.Delete(Path.Combine(m_MarkerPath,
78 scene.RegionInfo.RegionID.ToString()));
79
67 m_Scene = scene; 80 m_Scene = scene;
68 81
69 scene.RegisterModuleInterface<IRestartModule>(this); 82 scene.RegisterModuleInterface<IRestartModule>(this);
@@ -118,10 +131,14 @@ namespace OpenSim.Region.CoreModules.World.Region
118 public void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice) 131 public void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice)
119 { 132 {
120 if (m_CountdownTimer != null) 133 if (m_CountdownTimer != null)
121 return; 134 {
135 m_CountdownTimer.Stop();
136 m_CountdownTimer = null;
137 }
122 138
123 if (alerts == null) 139 if (alerts == null)
124 { 140 {
141 CreateMarkerFile();
125 m_Scene.RestartNow(); 142 m_Scene.RestartNow();
126 return; 143 return;
127 } 144 }
@@ -129,25 +146,28 @@ namespace OpenSim.Region.CoreModules.World.Region
129 m_Message = message; 146 m_Message = message;
130 m_Initiator = initiator; 147 m_Initiator = initiator;
131 m_Notice = notice; 148 m_Notice = notice;
149 m_CurrentAlerts = alerts;
132 m_Alerts = new List<int>(alerts); 150 m_Alerts = new List<int>(alerts);
133 m_Alerts.Sort(); 151 m_Alerts.Sort();
134 m_Alerts.Reverse(); 152 m_Alerts.Reverse();
135 153
136 if (m_Alerts[0] == 0) 154 if (m_Alerts[0] == 0)
137 { 155 {
156 CreateMarkerFile();
138 m_Scene.RestartNow(); 157 m_Scene.RestartNow();
139 return; 158 return;
140 } 159 }
141 160
142 int nextInterval = DoOneNotice(); 161 int nextInterval = DoOneNotice(true);
143 162
144 SetTimer(nextInterval); 163 SetTimer(nextInterval);
145 } 164 }
146 165
147 public int DoOneNotice() 166 public int DoOneNotice(bool sendOut)
148 { 167 {
149 if (m_Alerts.Count == 0 || m_Alerts[0] == 0) 168 if (m_Alerts.Count == 0 || m_Alerts[0] == 0)
150 { 169 {
170 CreateMarkerFile();
151 m_Scene.RestartNow(); 171 m_Scene.RestartNow();
152 return 0; 172 return 0;
153 } 173 }
@@ -168,34 +188,37 @@ namespace OpenSim.Region.CoreModules.World.Region
168 188
169 m_Alerts.RemoveAt(0); 189 m_Alerts.RemoveAt(0);
170 190
171 int minutes = currentAlert / 60; 191 if (sendOut)
172 string currentAlertString = String.Empty;
173 if (minutes > 0)
174 { 192 {
175 if (minutes == 1) 193 int minutes = currentAlert / 60;
176 currentAlertString += "1 minute"; 194 string currentAlertString = String.Empty;
177 else 195 if (minutes > 0)
178 currentAlertString += String.Format("{0} minutes", minutes); 196 {
197 if (minutes == 1)
198 currentAlertString += "1 minute";
199 else
200 currentAlertString += String.Format("{0} minutes", minutes);
201 if ((currentAlert % 60) != 0)
202 currentAlertString += " and ";
203 }
179 if ((currentAlert % 60) != 0) 204 if ((currentAlert % 60) != 0)
180 currentAlertString += " and "; 205 {
181 } 206 int seconds = currentAlert % 60;
182 if ((currentAlert % 60) != 0) 207 if (seconds == 1)
183 { 208 currentAlertString += "1 second";
184 int seconds = currentAlert % 60; 209 else
185 if (seconds == 1) 210 currentAlertString += String.Format("{0} seconds", seconds);
186 currentAlertString += "1 second"; 211 }
187 else
188 currentAlertString += String.Format("{0} seconds", seconds);
189 }
190 212
191 string msg = String.Format(m_Message, currentAlertString); 213 string msg = String.Format(m_Message, currentAlertString);
192 214
193 if (m_DialogModule != null && msg != String.Empty) 215 if (m_DialogModule != null && msg != String.Empty)
194 { 216 {
195 if (m_Notice) 217 if (m_Notice)
196 m_DialogModule.SendGeneralAlert(msg); 218 m_DialogModule.SendGeneralAlert(msg);
197 else 219 else
198 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg); 220 m_DialogModule.SendNotificationToUsersInRegion(m_Initiator, "System", msg);
221 }
199 } 222 }
200 223
201 return currentAlert - nextAlert; 224 return currentAlert - nextAlert;
@@ -226,7 +249,27 @@ namespace OpenSim.Region.CoreModules.World.Region
226 249
227 private void OnTimer(object source, ElapsedEventArgs e) 250 private void OnTimer(object source, ElapsedEventArgs e)
228 { 251 {
229 SetTimer(DoOneNotice()); 252 int nextInterval = DoOneNotice(true);
253
254 SetTimer(nextInterval);
255 }
256
257 public void DelayRestart(int seconds, string message)
258 {
259 if (m_CountdownTimer == null)
260 return;
261
262 m_CountdownTimer.Stop();
263 m_CountdownTimer = null;
264
265 m_Alerts = new List<int>(m_CurrentAlerts);
266 m_Alerts.Add(seconds);
267 m_Alerts.Sort();
268 m_Alerts.Reverse();
269
270 int nextInterval = DoOneNotice(false);
271
272 SetTimer(nextInterval);
230 } 273 }
231 274
232 public void AbortRestart(string message) 275 public void AbortRestart(string message)
@@ -236,8 +279,12 @@ namespace OpenSim.Region.CoreModules.World.Region
236 m_CountdownTimer.Stop(); 279 m_CountdownTimer.Stop();
237 m_CountdownTimer = null; 280 m_CountdownTimer = null;
238 if (m_DialogModule != null && message != String.Empty) 281 if (m_DialogModule != null && message != String.Empty)
239 m_DialogModule.SendGeneralAlert(message); 282 m_DialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message);
283 //m_DialogModule.SendGeneralAlert(message);
240 } 284 }
285 if (m_MarkerPath != String.Empty)
286 File.Delete(Path.Combine(m_MarkerPath,
287 m_Scene.RegionInfo.RegionID.ToString()));
241 } 288 }
242 289
243 private void HandleRegionRestart(string module, string[] args) 290 private void HandleRegionRestart(string module, string[] args)
@@ -282,5 +329,25 @@ namespace OpenSim.Region.CoreModules.World.Region
282 329
283 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 330 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
284 } 331 }
332
333 protected void CreateMarkerFile()
334 {
335 if (m_MarkerPath == String.Empty)
336 return;
337
338 string path = Path.Combine(m_MarkerPath, m_Scene.RegionInfo.RegionID.ToString());
339 try
340 {
341 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
342 FileStream fs = File.Create(path);
343 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
344 Byte[] buf = enc.GetBytes(pidstring);
345 fs.Write(buf, 0, buf.Length);
346 fs.Close();
347 }
348 catch (Exception)
349 {
350 }
351 }
285 } 352 }
286} \ No newline at end of file 353}
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index d093224..9c99c19 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -48,6 +48,18 @@ namespace OpenSim.Region.CoreModules.World.Sound
48 48
49 private Scene m_scene; 49 private Scene m_scene;
50 50
51 public enum SoundFlags: byte
52 {
53 NONE = 0,
54 LOOP = 1 << 0,
55 SYNC_MASTER = 1<<1,
56 SYNC_SLAVE = 1<<2,
57 SYNC_PENDING = 1<<3,
58 QUEUE = 1<<4,
59 STOP = 1<<5,
60 SYNC_MASK = SYNC_MASTER | SYNC_SLAVE | SYNC_PENDING
61 }
62
51 public bool Enabled { get; private set; } 63 public bool Enabled { get; private set; }
52 64
53 public float MaxDistance { get; private set; } 65 public float MaxDistance { get; private set; }
@@ -124,26 +136,30 @@ namespace OpenSim.Region.CoreModules.World.Sound
124 if (radius == 0) 136 if (radius == 0)
125 radius = MaxDistance; 137 radius = MaxDistance;
126 138
127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 139 if (part.SoundQueueing)
140 flags |= (byte)SoundFlags.QUEUE;
141
142 if (grp.IsAttachment)
128 { 143 {
129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 144 ScenePresence ssp = null;
130 if (dis > MaxDistance) // Max audio distance 145 if (!m_scene.TryGetScenePresence(grp.AttachedAvatar, out ssp))
131 return; 146 return;
132 147
133 if (grp.IsAttachment) 148 if (!ssp.ParcelAllowThisAvatarSounds)
134 { 149 return;
135 if (grp.HasPrivateAttachmentPoint && sp.ControllingClient.AgentId != grp.OwnerID)
136 return;
137 150
138 if (sp.ControllingClient.AgentId == grp.OwnerID) 151 if (grp.HasPrivateAttachmentPoint)
139 dis = 0; 152 {
153 ssp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
154 ownerID, (float)gain, flags);
155 return;
140 } 156 }
157 }
141 158
142 // Scale by distance 159 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
143 double thisSpGain = gain * ((radius - dis) / radius); 160 {
144
145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, 161 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
146 ownerID, (float)thisSpGain, flags); 162 ownerID, (float)gain, flags);
147 }); 163 });
148 } 164 }
149 165
@@ -151,20 +167,33 @@ namespace OpenSim.Region.CoreModules.World.Sound
151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 167 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
152 { 168 {
153 SceneObjectPart part; 169 SceneObjectPart part;
170 ScenePresence ssp = null;
154 if (!m_scene.TryGetSceneObjectPart(objectID, out part)) 171 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
155 { 172 {
156 ScenePresence sp; 173 if (!m_scene.TryGetScenePresence(ownerID, out ssp))
157 if (!m_scene.TryGetScenePresence(ownerID, out sp)) 174 return;
175 if (!ssp.ParcelAllowThisAvatarSounds)
158 return; 176 return;
159 } 177 }
160 else 178 else
161 { 179 {
162 SceneObjectGroup grp = part.ParentGroup; 180 SceneObjectGroup grp = part.ParentGroup;
163 181
164 if (grp.IsAttachment && grp.AttachmentPoint > 30) 182 if (grp.IsAttachment)
165 { 183 {
166 objectID = ownerID; 184 if (!m_scene.TryGetScenePresence(grp.AttachedAvatar, out ssp))
167 parentID = ownerID; 185 return;
186
187 if (!ssp.ParcelAllowThisAvatarSounds)
188 return;
189
190 if (grp.HasPrivateAttachmentPoint)
191 {
192 ssp.ControllingClient.SendTriggeredSound(soundId, ownerID,
193 objectID, parentID, handle, position,
194 (float)gain);
195 return;
196 }
168 } 197 }
169 } 198 }
170 199
@@ -174,16 +203,12 @@ namespace OpenSim.Region.CoreModules.World.Sound
174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 203 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
175 { 204 {
176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 205 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
177 206 if (dis > radius) // Max audio distance
178 if (dis > MaxDistance) // Max audio distance
179 return; 207 return;
180 208
181 // Scale by distance
182 double thisSpGain = gain * ((radius - dis) / radius);
183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID, 209 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position, 210 objectID, parentID, handle, position,
186 (float)thisSpGain); 211 (float)gain);
187 }); 212 });
188 } 213 }
189 214
@@ -198,40 +223,13 @@ namespace OpenSim.Region.CoreModules.World.Sound
198 223
199 private static void StopSound(SceneObjectPart m_host) 224 private static void StopSound(SceneObjectPart m_host)
200 { 225 {
201 m_host.AdjustSoundGain(0); 226// m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead 227 m_host.Sound = UUID.Zero;
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) 228 m_host.SoundFlags = (byte)SoundFlags.STOP;
204 { 229 m_host.SoundRadius = 0;
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) 230 m_host.SoundGain = 0;
206 { 231 m_host.ScheduleFullUpdate();
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) 232 m_host.SendFullUpdateToAllClients();
208 {
209 part.Sound = UUID.Zero;
210 part.SoundFlags = 1 << 5;
211 part.SoundRadius = 0;
212 part.ScheduleFullUpdate();
213 part.SendFullUpdateToAllClients();
214 }
215 m_host.ParentGroup.LoopSoundMasterPrim = null;
216 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
217 }
218 else
219 {
220 m_host.Sound = UUID.Zero;
221 m_host.SoundFlags = 1 << 5;
222 m_host.SoundRadius = 0;
223 m_host.ScheduleFullUpdate();
224 m_host.SendFullUpdateToAllClients();
225 }
226 }
227 else
228 {
229 m_host.Sound = UUID.Zero;
230 m_host.SoundFlags = 1 << 5;
231 m_host.SoundRadius = 0;
232 m_host.ScheduleFullUpdate();
233 m_host.SendFullUpdateToAllClients();
234 }
235 } 233 }
236 234
237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) 235 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
@@ -248,7 +246,7 @@ namespace OpenSim.Region.CoreModules.World.Sound
248 246
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 247 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 { 248 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) 249 if (Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) < radius)
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); 250 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
253 }); 251 });
254 } 252 }
@@ -262,21 +260,24 @@ namespace OpenSim.Region.CoreModules.World.Sound
262 // 20080530 Updated to remove code duplication 260 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work 261 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID, 262 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster) 263 double volume, double radius, bool isMaster, bool isSlave)
266 { 264 {
267 SceneObjectPart m_host; 265 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) 266 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return; 267 return;
270 268
269 byte iflags = 1; // looping
271 if (isMaster) 270 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host; 271 iflags |= (byte)SoundFlags.SYNC_MASTER;
273 272 // TODO check viewer seems to accept both
274 if (m_host.Sound != UUID.Zero) 273 if (isSlave)
275 StopSound(m_host); 274 iflags |= (byte)SoundFlags.SYNC_SLAVE;
275 if (m_host.SoundQueueing)
276 iflags |= (byte)SoundFlags.QUEUE;
276 277
277 m_host.Sound = soundID; 278 m_host.Sound = soundID;
278 m_host.SoundGain = volume; 279 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping 280 m_host.SoundFlags = iflags;
280 m_host.SoundRadius = radius; 281 m_host.SoundRadius = radius;
281 282
282 m_host.ScheduleFullUpdate(); 283 m_host.ScheduleFullUpdate();
@@ -301,42 +302,19 @@ namespace OpenSim.Region.CoreModules.World.Sound
301 Vector3 position = part.AbsolutePosition; // region local 302 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle; 303 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303 304
304 if (useMaster) 305 if(triggered)
305 { 306 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
306 if (isMaster)
307 {
308 if (triggered)
309 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
310 else
311 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
312 part.ParentGroup.PlaySoundMasterPrim = part;
313 if (triggered)
314 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
315 else
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
317 foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
318 {
319 position = prim.AbsolutePosition; // region local
320 if (triggered)
321 TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
322 else
323 PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
324 }
325 part.ParentGroup.PlaySoundSlavePrims.Clear();
326 part.ParentGroup.PlaySoundMasterPrim = null;
327 }
328 else
329 {
330 part.ParentGroup.PlaySoundSlavePrims.Add(part);
331 }
332 }
333 else 307 else
334 { 308 {
335 if (triggered) 309 byte bflags = 0;
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); 310
337 else 311 if (isMaster)
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); 312 bflags |= (byte)SoundFlags.SYNC_MASTER;
339 } 313 // TODO check viewer seems to accept both
314 if (useMaster)
315 bflags |= (byte)SoundFlags.SYNC_SLAVE;
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, bflags, radius);
317 }
340 } 318 }
341 319
342 public void TriggerSoundLimited(UUID objectID, UUID sound, 320 public void TriggerSoundLimited(UUID objectID, UUID sound,
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
index 36917e9..b456aa1 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/ChannelDigger.cs
@@ -64,7 +64,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
64 64
65 for (int i = 0; i < rounds; i++) 65 for (int i = 0; i < rounds; i++)
66 { 66 {
67 smoothFunction.FloodEffect(map, bitmap, 1.0); 67 smoothFunction.FloodEffect(map, bitmap, 1.0, 0, map.Width - 1, 0, map.Height - 1);
68 } 68 }
69 } 69 }
70 70
@@ -99,7 +99,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
99 } 99 }
100 } 100 }
101 101
102 raiseFunction.FloodEffect(map, bitmap, height); 102 raiseFunction.FloodEffect(map, bitmap, height, 0, map.Width - 1, 0, map.Height - 1);
103 } 103 }
104 } 104 }
105 } 105 }
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
index dc76ad5..3222524 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/CookieCutter.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
84 for (y = 0; y < map.Height; y++) 84 for (y = 0; y < map.Height; y++)
85 { 85 {
86 if (cliffMask[x, y]) 86 if (cliffMask[x, y])
87 eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1); 87 eroder.PaintEffect(map, allowMask, x, y, -1, 4, 0.1,0,map.Width - 1,0,map.Height - 1);
88 } 88 }
89 } 89 }
90 90
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
index 89087b1..80396c4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Effects/DefaultTerrainGenerator.cs
@@ -53,4 +53,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Effects
53 53
54 #endregion 54 #endregion
55 } 55 }
56} \ No newline at end of file 56}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
index d5c77ec..e8c719a 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/GenericSystemDrawing.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
128 colours.Save(stream, ImageFormat.Png); 128 colours.Save(stream, ImageFormat.Png);
129 } 129 }
130 130
131 public virtual void SaveFile(ITerrainChannel m_channel, string filename, 131 public virtual void SaveFile(ITerrainChannel m_channel, string filename,
132 int offsetX, int offsetY, 132 int offsetX, int offsetY,
133 int fileWidth, int fileHeight, 133 int fileWidth, int fileHeight,
134 int regionSizeX, int regionSizeY) 134 int regionSizeX, int regionSizeY)
@@ -162,13 +162,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
162 { 162 {
163 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY); 163 newBitmap = new Bitmap(fileWidth * regionSizeX, fileHeight * regionSizeY);
164 } 164 }
165 165
166 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel); 166 thisBitmap = CreateGrayscaleBitmapFromMap(m_channel);
167 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY); 167 // Console.WriteLine("offsetX=" + offsetX + " offsetY=" + offsetY);
168 for (int x = 0; x < regionSizeX; x++) 168 for (int x = 0; x < regionSizeX; x++)
169 for (int y = 0; y < regionSizeY; y++) 169 for (int y = 0; y < regionSizeY; y++)
170 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y)); 170 newBitmap.SetPixel(x + offsetX * regionSizeX, y + (fileHeight - 1 - offsetY) * regionSizeY, thisBitmap.GetPixel(x, y));
171 171
172 Save(newBitmap, filename); 172 Save(newBitmap, filename);
173 } 173 }
174 finally 174 finally
@@ -213,8 +213,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
213 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns> 213 /// <returns>A System.Drawing.Bitmap containing a grayscale image</returns>
214 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map) 214 protected static Bitmap CreateGrayscaleBitmapFromMap(ITerrainChannel map)
215 { 215 {
216 // Bitmap bmp = new Bitmap(map.Width, map.Height, PixelFormat.Format24bppRgb);
216 Bitmap bmp = new Bitmap(map.Width, map.Height); 217 Bitmap bmp = new Bitmap(map.Width, map.Height);
217 218
219
218 const int pallete = 256; 220 const int pallete = 256;
219 221
220 Color[] grays = new Color[pallete]; 222 Color[] grays = new Color[pallete];
@@ -227,59 +229,24 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
227 { 229 {
228 for (int x = 0; x < map.Width; x++) 230 for (int x = 0; x < map.Width; x++)
229 { 231 {
230 // 512 is the largest possible height before colours clamp 232 // to change this, loading also needs change
231 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 128.0), 0.0) * (pallete - 1));
232
233 // Handle error conditions
234 if (colorindex > pallete - 1 || colorindex < 0)
235 bmp.SetPixel(x, map.Height - y - 1, Color.Red);
236 else
237 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]);
238 }
239 }
240 return bmp;
241 }
242
243 /// <summary>
244 /// Protected method, generates a coloured bitmap
245 /// image from a specified terrain channel.
246 /// </summary>
247 /// <param name="map">The terrain channel to export to bitmap</param>
248 /// <returns>A System.Drawing.Bitmap containing a coloured image</returns>
249 protected static Bitmap CreateBitmapFromMap(ITerrainChannel map)
250 {
251 int pallete;
252 Bitmap bmp;
253 Color[] colours;
254 233
255 using (Bitmap gradientmapLd = new Bitmap("defaultstripe.png")) 234 // int colorindex = (int)map[x, y]; // one to one conversion 0 - 255m range
256 { 235 // int colorindex = (int)map[x, y] / 2; // 0 - 510 range
257 pallete = gradientmapLd.Height;
258
259 bmp = new Bitmap(map.Width, map.Height);
260 colours = new Color[pallete];
261
262 for (int i = 0; i < pallete; i++)
263 {
264 colours[i] = gradientmapLd.GetPixel(0, i);
265 }
266 }
267 236
268 for (int y = 0; y < map.Height; y++) 237 int colorindex = (int)map[x, y] * 2; // the original 0 - 127.5 range
269 {
270 for (int x = 0; x < map.Width; x++)
271 {
272 // 512 is the largest possible height before colours clamp
273 int colorindex = (int) (Math.Max(Math.Min(1.0, map[x, y] / 512.0), 0.0) * (pallete - 1));
274 238
275 // Handle error conditions 239 // clamp it not adding the red warning
276 if (colorindex > pallete - 1 || colorindex < 0) 240 if (colorindex < 0)
277 bmp.SetPixel(x, map.Height - y - 1, Color.Red); 241 colorindex = 0;
278 else 242 else if (colorindex >= pallete)
279 bmp.SetPixel(x, map.Height - y - 1, colours[colorindex]); 243 colorindex = pallete - 1;
244 bmp.SetPixel(x, map.Height - y - 1, grays[colorindex]);
280 } 245 }
281 } 246 }
282 return bmp; 247 return bmp;
283 } 248 }
284 } 249 }
285} 250}
251
252
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
index be1fb24..59994e4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/LLRAW.cs
@@ -57,6 +57,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
57 57
58 public LLRAW() 58 public LLRAW()
59 { 59 {
60 }
61
62 private void BuildLookupHeightTable()
63 {
60 LookupHeightTable = new HeightmapLookupValue[256 * 256]; 64 LookupHeightTable = new HeightmapLookupValue[256 * 256];
61 65
62 for (int i = 0; i < 256; i++) 66 for (int i = 0; i < 256; i++)
@@ -186,6 +190,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
186 190
187 public void SaveStream(Stream s, ITerrainChannel map) 191 public void SaveStream(Stream s, ITerrainChannel map)
188 { 192 {
193 if (LookupHeightTable == null)
194 BuildLookupHeightTable();
195
189 using (BinaryWriter binStream = new BinaryWriter(s)) 196 using (BinaryWriter binStream = new BinaryWriter(s))
190 { 197 {
191 // Output the calculated raw 198 // Output the calculated raw
@@ -241,6 +248,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders
241 } 248 }
242 } 249 }
243 } 250 }
251 LookupHeightTable = null;
244 } 252 }
245 253
246 public string FileExtension 254 public string FileExtension
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
index 774e7b2..0c4171e 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/FlattenArea.cs
@@ -33,15 +33,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 double sum = 0.0; 39 double sum = 0.0;
39 double steps = 0.0; 40 double steps = 0.0;
40 41
41 int x, y; 42 int x, y;
42 for (x = 0; x < map.Width; x++) 43 for (x = startX; x <= endX; x++)
43 { 44 {
44 for (y = 0; y < map.Height; y++) 45 for (y = startY; y <= endY; y++)
45 { 46 {
46 if (fillArea[x, y]) 47 if (fillArea[x, y])
47 { 48 {
@@ -55,9 +56,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
55 56
56 double str = 0.1 * strength; // == 0.2 in the default client 57 double str = 0.1 * strength; // == 0.2 in the default client
57 58
58 for (x = 0; x < map.Width; x++) 59 for (x = startX; x <= endX; x++)
59 { 60 {
60 for (y = 0; y < map.Height; y++) 61 for (y = startY; y <= endY; y++)
61 { 62 {
62 if (fillArea[x, y]) 63 if (fillArea[x, y])
63 map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str); 64 map[x, y] = (map[x, y] * (1.0 - str)) + (avg * str);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
index 3e87390..a275a86 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/LowerArea.cs
@@ -33,13 +33,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 int x; 39 int x,y;
39 for (x = 0; x < map.Width; x++) 40 for (x = startX; x <= endX; x++)
40 { 41 {
41 int y; 42 for (y = startY; y <= endY; y++)
42 for (y = 0; y < map.Height; y++)
43 { 43 {
44 if (fillArea[x, y]) 44 if (fillArea[x, y])
45 { 45 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
index b6c635c..d634e8b 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/NoiseArea.cs
@@ -35,18 +35,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
35 { 35 {
36 #region ITerrainFloodEffect Members 36 #region ITerrainFloodEffect Members
37 37
38 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 38 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
39 int startX, int endX, int startY, int endY)
39 { 40 {
40 int x; 41 int x, y;
41 for (x = 0; x < map.Width; x++) 42 for (x = startX; x <= endX; x++)
42 { 43 {
43 int y; 44 for (y = startY; y <= endY; y++)
44 for (y = 0; y < map.Height; y++)
45 { 45 {
46 if (fillArea[x, y]) 46 if (fillArea[x, y])
47 { 47 {
48 double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0); 48 double noise = TerrainUtil.PerlinNoise2D((double) x / map.Width, (double) y / map.Height, 8, 1.0);
49
50 map[x, y] += noise * strength; 49 map[x, y] += noise * strength;
51 } 50 }
52 } 51 }
@@ -55,4 +54,4 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
55 54
56 #endregion 55 #endregion
57 } 56 }
58} \ No newline at end of file 57}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
index 3bdc5e7..6ccd5df 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RaiseArea.cs
@@ -33,13 +33,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 int x; 39 int x,y;
39 for (x = 0; x < map.Width; x++) 40 for (x = startX; x <= endX; x++)
40 { 41 {
41 int y; 42 for (y = startY; y <= endY; y++)
42 for (y = 0; y < map.Height; y++)
43 { 43 {
44 if (fillArea[x, y]) 44 if (fillArea[x, y])
45 { 45 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
index c5527fa..4230133 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/RevertArea.cs
@@ -46,13 +46,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
46 /// <param name="map">the current heightmap</param> 46 /// <param name="map">the current heightmap</param>
47 /// <param name="fillArea">array indicating which sections of the map are to be reverted</param> 47 /// <param name="fillArea">array indicating which sections of the map are to be reverted</param>
48 /// <param name="strength">unused</param> 48 /// <param name="strength">unused</param>
49 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 49 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
50 int startX, int endX, int startY, int endY)
50 { 51 {
51 int x; 52 int x, y;
52 for (x = 0; x < map.Width; x++) 53 for (x = startX; x <= endX; x++)
53 { 54 {
54 int y; 55 for (y = startY; y <= endY; y++)
55 for (y = 0; y < map.Height; y++)
56 { 56 {
57 if (fillArea[x, y]) 57 if (fillArea[x, y])
58 { 58 {
diff --git a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
index 6b07747..6c0d60d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/FloodBrushes/SmoothArea.cs
@@ -33,16 +33,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
33 { 33 {
34 #region ITerrainFloodEffect Members 34 #region ITerrainFloodEffect Members
35 35
36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength) 36 public void FloodEffect(ITerrainChannel map, bool[,] fillArea, double strength,
37 int startX, int endX, int startY, int endY)
37 { 38 {
38 double area = strength; 39 double area = strength;
39 double step = strength / 4.0; 40 double step = strength / 4.0;
40 41
41 double[,] manipulate = new double[map.Width,map.Height]; 42 double[,] manipulate = new double[map.Width,map.Height];
42 int x, y; 43 int x, y;
43 for (x = 0; x < map.Width; x++) 44 for (x = startX; x <= endX; x++)
44 { 45 {
45 for (y = 0; y < map.Height; y++) 46 for (y = startY; y <= endY; y++)
46 { 47 {
47 if (!fillArea[x, y]) 48 if (!fillArea[x, y])
48 continue; 49 continue;
@@ -64,9 +65,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FloodBrushes
64 manipulate[x, y] = average / avgsteps; 65 manipulate[x, y] = average / avgsteps;
65 } 66 }
66 } 67 }
67 for (x = 0; x < map.Width; x++) 68 for (x = startX; x <= endX; x++)
68 { 69 {
69 for (y = 0; y < map.Height; y++) 70 for (y = startY; y <= endY; y++)
70 { 71 {
71 if (!fillArea[x, y]) 72 if (!fillArea[x, y])
72 continue; 73 continue;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
index 3984a30..6324aca 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainFloodEffect.cs
@@ -32,6 +32,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
32{ 32{
33 public interface ITerrainFloodEffect 33 public interface ITerrainFloodEffect
34 { 34 {
35 void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength); 35 void FloodEffect(ITerrainChannel map, Boolean[,] fillArea, double strength,
36 int startX, int endX, int startY, int endY);
36 } 37 }
37} \ No newline at end of file 38} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs b/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
index b73defd..d0b05e4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/ITerrainPaintableEffect.cs
@@ -31,6 +31,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
31{ 31{
32 public interface ITerrainPaintableEffect 32 public interface ITerrainPaintableEffect
33 { 33 {
34 void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z, double strength, double duration); 34 void PaintEffect(ITerrainChannel map, bool[,] allowMask, double x, double y, double z,
35 double strength, double duration, int startX, int endX, int startY, int endY);
35 } 36 }
36} 37}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
index 7a78cd8..7358ba3 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/ErodeSphere.cs
@@ -151,7 +151,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
151 151
152 #region ITerrainPaintableEffect Members 152 #region ITerrainPaintableEffect Members
153 153
154 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 154 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
155 double strength, double duration, int startX, int endX, int startY, int endY)
155 { 156 {
156 strength = TerrainUtil.MetersToSphericalStrength(strength); 157 strength = TerrainUtil.MetersToSphericalStrength(strength);
157 158
@@ -163,18 +164,23 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
163 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height); 164 ITerrainChannel sediment = new TerrainChannel(map.Width, map.Height);
164 165
165 // Fill with rain 166 // Fill with rain
166 for (x = 0; x < water.Width; x++) 167 for (x = startX; x <= endX; x++)
167 for (y = 0; y < water.Height; y++) 168 {
168 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration); 169 for (y = startY; y <= endY; y++)
170 {
171 if (mask[x, y])
172 water[x, y] = Math.Max(0.0, TerrainUtil.SphericalFactor(x, y, rx, ry, strength) * rainHeight * duration);
173 }
174 }
169 175
170 for (int i = 0; i < rounds; i++) 176 for (int i = 0; i < rounds; i++)
171 { 177 {
172 // Erode underlying terrain 178 // Erode underlying terrain
173 for (x = 0; x < water.Width; x++) 179 for (x = startX; x <= endX; x++)
174 { 180 {
175 for (y = 0; y < water.Height; y++) 181 for (y = startY; y <= endY; y++)
176 { 182 {
177 if (mask[x,y]) 183 if (mask[x, y])
178 { 184 {
179 const double solConst = (1.0 / rounds); 185 const double solConst = (1.0 / rounds);
180 double sedDelta = water[x, y] * solConst; 186 double sedDelta = water[x, y] * solConst;
@@ -185,9 +191,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
185 } 191 }
186 192
187 // Move water 193 // Move water
188 for (x = 0; x < water.Width; x++) 194 for (x = startX; x <= endX; x++)
189 { 195 {
190 for (y = 0; y < water.Height; y++) 196 for (y = startY; y <= endY; y++)
191 { 197 {
192 if (water[x, y] <= 0) 198 if (water[x, y] <= 0)
193 continue; 199 continue;
@@ -296,7 +302,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
296 double sedimentDeposit = sediment[x, y] - waterCapacity; 302 double sedimentDeposit = sediment[x, y] - waterCapacity;
297 if (sedimentDeposit > 0) 303 if (sedimentDeposit > 0)
298 { 304 {
299 if (mask[x,y]) 305 if (mask[x, y])
300 { 306 {
301 sediment[x, y] -= sedimentDeposit; 307 sediment[x, y] -= sedimentDeposit;
302 map[x, y] += sedimentDeposit; 308 map[x, y] += sedimentDeposit;
@@ -309,10 +315,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
309 // Deposit any remainder (should be minimal) 315 // Deposit any remainder (should be minimal)
310 for (x = 0; x < water.Width; x++) 316 for (x = 0; x < water.Width; x++)
311 for (y = 0; y < water.Height; y++) 317 for (y = 0; y < water.Height; y++)
312 if (mask[x,y] && sediment[x, y] > 0) 318 if (mask[x, y] && sediment[x, y] > 0)
313 map[x, y] += sediment[x, y]; 319 map[x, y] += sediment[x, y];
314 } 320 }
315
316 #endregion 321 #endregion
317 } 322 }
318} 323}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
index 9aa3dff..8937f63 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/FlattenSphere.cs
@@ -35,16 +35,17 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
35 { 35 {
36 #region ITerrainPaintableEffect Members 36 #region ITerrainPaintableEffect Members
37 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 strength = TerrainUtil.MetersToSphericalStrength(strength); 41 strength = TerrainUtil.MetersToSphericalStrength(strength);
41 42
42 int x, y; 43 int x, y;
43 44
44 // blend in map 45 // blend in map
45 for (x = 0; x < map.Width; x++) 46 for (x = startX; x <= endX; x++)
46 { 47 {
47 for (y = 0; y < map.Height; y++) 48 for (y = startY; y <= endY; y++)
48 { 49 {
49 if (!mask[x,y]) 50 if (!mask[x,y])
50 continue; 51 continue;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
index 68145f2..bbf9407 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/LowerSphere.cs
@@ -34,34 +34,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
34 { 34 {
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36 36
37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
38 double strength, double duration, int startX, int endX, int startY, int endY)
38 { 39 {
39 int s = (int) (Math.Pow(2, strength) + 0.5); 40 int s = (int) (Math.Pow(2, strength) + 0.5);
40 41
41 int x; 42 int x, y;
42 int xFrom = (int)(rx-s+0.5);
43 int xTo = (int)(rx+s+0.5) + 1;
44 int yFrom = (int)(ry-s+0.5);
45 int yTo = (int)(ry+s+0.5) + 1;
46 43
47 if (xFrom < 0) 44 for (x = startX; x <= endX; x++)
48 xFrom = 0;
49
50 if (yFrom < 0)
51 yFrom = 0;
52
53 if (xTo > map.Width)
54 xTo = map.Width;
55
56 if (yTo > map.Width)
57 yTo = map.Width;
58
59 for (x = xFrom; x < xTo; x++)
60 { 45 {
61 int y; 46 for (y = startY; y <= endY; y++)
62 for (y = yFrom; y < yTo; y++)
63 { 47 {
64 if (!mask[x,y]) 48 if (!mask[x, y])
65 continue; 49 continue;
66 50
67 // Calculate a cos-sphere and add it to the heighmap 51 // Calculate a cos-sphere and add it to the heighmap
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
index e7df3f8..46d47b4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/NoiseSphere.cs
@@ -35,17 +35,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
35 { 35 {
36 #region ITerrainPaintableEffect Members 36 #region ITerrainPaintableEffect Members
37 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 strength = TerrainUtil.MetersToSphericalStrength(strength); 41 strength = TerrainUtil.MetersToSphericalStrength(strength);
41 42
42 int x; 43 int x, y;
43 for (x = 0; x < map.Width; x++) 44
45 for (x = startX; x <= endX; x++)
44 { 46 {
45 int y; 47 for (y = startY; y <= endY; y++)
46 for (y = 0; y < map.Height; y++)
47 { 48 {
48 if (!mask[x,y]) 49 if (!mask[x, y])
49 continue; 50 continue;
50 51
51 // Calculate a sphere and add it to the heighmap 52 // Calculate a sphere and add it to the heighmap
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
index b199df3..281690d 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/OlsenSphere.cs
@@ -152,18 +152,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
152 152
153 #region ITerrainPaintableEffect Members 153 #region ITerrainPaintableEffect Members
154 154
155 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 155 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
156 double strength, double duration, int startX, int endX, int startY, int endY)
156 { 157 {
157 strength = TerrainUtil.MetersToSphericalStrength(strength); 158 strength = TerrainUtil.MetersToSphericalStrength(strength);
158 159
159 int x; 160 int x, y;
160 161
161 for (x = 0; x < map.Width; x++) 162 for (x = startX; x <= endX; x++)
162 { 163 {
163 int y; 164 for (y = startY; y <= endY; y++)
164 for (y = 0; y < map.Height; y++)
165 { 165 {
166 if (!mask[x,y]) 166 if (!mask[x, y])
167 continue; 167 continue;
168 168
169 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 169 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
index bd9a8a0..1b704bb 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RaiseSphere.cs
@@ -35,38 +35,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36 36
37 37
38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 38 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
39 double strength, double duration, int startX, int endX, int startY, int endY)
39 { 40 {
40 int s = (int) (Math.Pow(2, strength) + 0.5); 41 int s = (int) (Math.Pow(2, strength) + 0.5);
41 42
42 int x; 43 int x,y;
43 int xFrom = (int)(rx-s+0.5);
44 int xTo = (int)(rx+s+0.5) + 1;
45 int yFrom = (int)(ry-s+0.5);
46 int yTo = (int)(ry+s+0.5) + 1;
47 44
48 if (xFrom < 0) 45 for (x = startX; x <= endX; x++)
49 xFrom = 0;
50
51 if (yFrom < 0)
52 yFrom = 0;
53
54 if (xTo > map.Width)
55 xTo = map.Width;
56
57 if (yTo > map.Width)
58 yTo = map.Width;
59
60 for (x = xFrom; x < xTo; x++)
61 { 46 {
62 int y; 47 for (y = startY; y <= endY; y++)
63 for (y = yFrom; y < yTo; y++)
64 { 48 {
65 if (!mask[x,y]) 49 if (!mask[x, y])
66 continue; 50 continue;
67 51
68 // Calculate a cos-sphere and add it to the heighmap 52 // Calculate a cos-sphere and add it to the heighmap
69 double r = Math.Sqrt((x-rx) * (x-rx) + ((y-ry) * (y-ry))); 53 double r = Math.Sqrt((x - rx) * (x - rx) + ((y - ry) * (y - ry)));
70 double z = Math.Cos(r * Math.PI / (s * 2)); 54 double z = Math.Cos(r * Math.PI / (s * 2));
71 if (z > 0.0) 55 if (z > 0.0)
72 map[x, y] += z * duration; 56 map[x, y] += z * duration;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
index 4b28275..efc5324 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/RevertSphere.cs
@@ -41,7 +41,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
41 41
42 #region ITerrainPaintableEffect Members 42 #region ITerrainPaintableEffect Members
43 43
44 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 44 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
45 double strength, double duration, int startX, int endX, int startY, int endY)
45 { 46 {
46 strength = TerrainUtil.MetersToSphericalStrength(strength); 47 strength = TerrainUtil.MetersToSphericalStrength(strength);
47 duration = 0.03; //MCP Should be read from ini file 48 duration = 0.03; //MCP Should be read from ini file
@@ -51,13 +52,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
51 if (duration < 0) 52 if (duration < 0)
52 return; 53 return;
53 54
54 int x; 55 int x,y;
55 for (x = 0; x < map.Width; x++) 56 for (x = startX; x <= endX; x++)
56 { 57 {
57 int y; 58 for (y = startY; y <= endY; y++)
58 for (y = 0; y < map.Height; y++)
59 { 59 {
60 if (!mask[x,y]) 60 if (!mask[x, y])
61 continue; 61 continue;
62 62
63 // Calculate a sphere and add it to the heighmap 63 // Calculate a sphere and add it to the heighmap
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
index 4834c86..65dd0a6 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/SmoothSphere.cs
@@ -34,7 +34,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
34 { 34 {
35 #region ITerrainPaintableEffect Members 35 #region ITerrainPaintableEffect Members
36 36
37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 37 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
38 double strength, double duration, int startX, int endX, int startY, int endY)
38 { 39 {
39 strength = TerrainUtil.MetersToSphericalStrength(strength); 40 strength = TerrainUtil.MetersToSphericalStrength(strength);
40 41
@@ -47,10 +48,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
47 48
48 49
49 // compute delta map 50 // compute delta map
50 for (x = 0; x < map.Width; x++) 51 for (x = startX; x <= endX; x++)
51 { 52 {
52 for (y = 0; y < map.Height; y++) 53 for (y = startY; y <= endY; y++)
53 { 54 {
55 if (!mask[x, y])
56 continue;
57
54 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 58 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
55 59
56 if (z > 0) // add in non-zero amount 60 if (z > 0) // add in non-zero amount
@@ -73,11 +77,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
73 } 77 }
74 } 78 }
75 // blend in map 79 // blend in map
76 for (x = 0; x < map.Width; x++) 80 for (x = startX; x <= endX; x++)
77 { 81 {
78 for (y = 0; y < map.Height; y++) 82 for (y = startY; y <= endY; y++)
79 { 83 {
80 if (!mask[x,y]) 84 if (!mask[x, y])
81 continue; 85 continue;
82 86
83 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength); 87 double z = TerrainUtil.SphericalFactor(x, y, rx, ry, strength);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
index f31c8b6..f52fe07 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/PaintBrushes/WeatherSphere.cs
@@ -148,16 +148,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain.PaintBrushes
148 148
149 #region ITerrainPaintableEffect Members 149 #region ITerrainPaintableEffect Members
150 150
151 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz, double strength, double duration) 151 public void PaintEffect(ITerrainChannel map, bool[,] mask, double rx, double ry, double rz,
152 double strength, double duration, int startX, int endX, int startY, int endY)
152 { 153 {
153 strength = TerrainUtil.MetersToSphericalStrength(strength); 154 strength = TerrainUtil.MetersToSphericalStrength(strength);
154 155
155 int x; 156 int x,y;
156 157
157 for (x = 0; x < map.Width; x++) 158 for (x = startX; x <= endX; x++)
158 { 159 {
159 int y; 160 for (y = startY; y <= endY; y++)
160 for (y = 0; y < map.Height; y++)
161 { 161 {
162 if (!mask[x,y]) 162 if (!mask[x,y])
163 continue; 163 continue;
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
index 7ebd08e..c6e992f 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModifier.cs
@@ -370,9 +370,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
370 } 370 }
371 return mask; 371 return mask;
372 } 372 }
373
374
375 } 373 }
376
377} 374}
378 375
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 932652c..5e35d95 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -29,6 +29,7 @@ using System.Collections.Generic;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Net; 31using System.Net;
32using System.Threading;
32 33
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
@@ -36,7 +37,6 @@ using Nini.Config;
36using OpenMetaverse; 37using OpenMetaverse;
37using Mono.Addins; 38using Mono.Addins;
38 39
39using OpenSim.Data;
40using OpenSim.Framework; 40using OpenSim.Framework;
41using OpenSim.Framework.Console; 41using OpenSim.Framework.Console;
42using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 42using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
@@ -86,14 +86,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
86 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>(); 86 private readonly Dictionary<string, ITerrainLoader> m_loaders = new Dictionary<string, ITerrainLoader>();
87 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects = 87 private readonly Dictionary<StandardTerrainEffects, ITerrainPaintableEffect> m_painteffects =
88 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>(); 88 new Dictionary<StandardTerrainEffects, ITerrainPaintableEffect>();
89 private Dictionary<string, ITerrainEffect> m_plugineffects;
90 private Dictionary<string, ITerrainModifier> m_modifyOperations = 89 private Dictionary<string, ITerrainModifier> m_modifyOperations =
91 new Dictionary<string, ITerrainModifier>(); 90 new Dictionary<string, ITerrainModifier>();
91 private Dictionary<string, ITerrainEffect> m_plugineffects;
92 private ITerrainChannel m_channel; 92 private ITerrainChannel m_channel;
93 private ITerrainChannel m_revert; 93 private ITerrainChannel m_baked;
94 private Scene m_scene; 94 private Scene m_scene;
95 private volatile bool m_tainted; 95 private volatile bool m_tainted;
96 private readonly Stack<LandUndoState> m_undo = new Stack<LandUndoState>(5); 96
97 private String m_InitialTerrain = "pinhead-island"; 97 private String m_InitialTerrain = "pinhead-island";
98 98
99 // If true, send terrain patch updates to clients based on their view distance 99 // If true, send terrain patch updates to clients based on their view distance
@@ -107,13 +107,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
107 private bool[,] updated; // for each patch, whether it needs to be sent to this client 107 private bool[,] updated; // for each patch, whether it needs to be sent to this client
108 private int updateCount; // number of patches that need to be sent 108 private int updateCount; // number of patches that need to be sent
109 public ScenePresence Presence; // a reference to the client to send to 109 public ScenePresence Presence; // a reference to the client to send to
110 public TerrainData Terrain; // reference to the underlying terrain 110 public bool sendAll;
111 public int sendAllcurrentX;
112 public int sendAllcurrentY;
113
114
111 public PatchUpdates(TerrainData terrData, ScenePresence pPresence) 115 public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
112 { 116 {
113 updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize]; 117 updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
114 updateCount = 0; 118 updateCount = 0;
115 Presence = pPresence; 119 Presence = pPresence;
116 Terrain = terrData;
117 // Initially, send all patches to the client 120 // Initially, send all patches to the client
118 SetAll(true); 121 SetAll(true);
119 } 122 }
@@ -146,12 +149,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain
146 public void SetAll(bool state) 149 public void SetAll(bool state)
147 { 150 {
148 updateCount = 0; 151 updateCount = 0;
149 for(int xx = 0; xx < updated.GetLength(0); xx++) 152 for (int xx = 0; xx < updated.GetLength(0); xx++)
150 for(int yy = 0; yy < updated.GetLength(1); yy++) 153 for (int yy = 0; yy < updated.GetLength(1); yy++)
151 updated[xx, yy] = state; 154 updated[xx, yy] = state;
152 if (state) 155 if (state)
153 updateCount = updated.GetLength(0) * updated.GetLength(1); 156 updateCount = updated.GetLength(0) * updated.GetLength(1);
157 sendAllcurrentX = 0;
158 sendAllcurrentY = 0;
159 sendAll = true;
154 } 160 }
161
155 // Logically OR's the terrain data's patch taint map into this client's update map. 162 // Logically OR's the terrain data's patch taint map into this client's update map.
156 public void SetAll(TerrainData terrData) 163 public void SetAll(TerrainData terrData)
157 { 164 {
@@ -164,9 +171,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
164 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize) 171 terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
165 ); 172 );
166 } 173 }
167 for(int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize) 174
175 for (int xx = 0; xx < terrData.SizeX; xx += Constants.TerrainPatchSize)
168 { 176 {
169 for(int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize) 177 for (int yy = 0; yy < terrData.SizeY; yy += Constants.TerrainPatchSize)
170 { 178 {
171 // Only set tainted. The patch bit may be set if the patch was to be sent later. 179 // Only set tainted. The patch bit may be set if the patch was to be sent later.
172 if (terrData.IsTaintedAt(xx, yy, false)) 180 if (terrData.IsTaintedAt(xx, yy, false))
@@ -210,7 +218,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
210 if (terrainConfig != null) 218 if (terrainConfig != null)
211 { 219 {
212 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 220 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
213 m_sendTerrainUpdatesByViewDistance = terrainConfig.GetBoolean("SendTerrainUpdatesByViewDistance", m_sendTerrainUpdatesByViewDistance); 221 m_sendTerrainUpdatesByViewDistance =
222 terrainConfig.GetBoolean(
223 "SendTerrainUpdatesByViewDistance",m_sendTerrainUpdatesByViewDistance);
214 } 224 }
215 } 225 }
216 226
@@ -227,12 +237,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
227 (int)m_scene.RegionInfo.RegionSizeY, 237 (int)m_scene.RegionInfo.RegionSizeY,
228 (int)m_scene.RegionInfo.RegionSizeZ); 238 (int)m_scene.RegionInfo.RegionSizeZ);
229 m_scene.Heightmap = m_channel; 239 m_scene.Heightmap = m_channel;
230 UpdateRevertMap(); 240
241 UpdateBakedMap();
231 } 242 }
232 else 243 else
233 { 244 {
234 m_channel = m_scene.Heightmap; 245 m_channel = m_scene.Heightmap;
235 UpdateRevertMap(); 246 UpdateBakedMap();
236 } 247 }
237 248
238 m_scene.RegisterModuleInterface<ITerrainModule>(this); 249 m_scene.RegisterModuleInterface<ITerrainModule>(this);
@@ -240,7 +251,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
240 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed; 251 m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
241 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; 252 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
242 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; 253 m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick;
243 m_scene.EventManager.OnFrame += EventManager_OnFrame; 254 m_scene.EventManager.OnTerrainCheckUpdates += EventManager_TerrainCheckUpdates;
244 } 255 }
245 256
246 InstallDefaultEffects(); 257 InstallDefaultEffects();
@@ -279,7 +290,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
279 // remove the commands 290 // remove the commands
280 m_scene.UnregisterModuleCommander(m_commander.Name); 291 m_scene.UnregisterModuleCommander(m_commander.Name);
281 // remove the event-handlers 292 // remove the event-handlers
282 m_scene.EventManager.OnFrame -= EventManager_OnFrame; 293
294 m_scene.EventManager.OnTerrainCheckUpdates -= EventManager_TerrainCheckUpdates;
283 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick; 295 m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick;
284 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; 296 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
285 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed; 297 m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
@@ -334,7 +346,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
334 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height); 346 m_log.DebugFormat("[TERRAIN]: Loaded terrain, wd/ht: {0}/{1}", channel.Width, channel.Height);
335 m_scene.Heightmap = channel; 347 m_scene.Heightmap = channel;
336 m_channel = channel; 348 m_channel = channel;
337 UpdateRevertMap(); 349 UpdateBakedMap();
338 } 350 }
339 catch(NotImplementedException) 351 catch(NotImplementedException)
340 { 352 {
@@ -426,7 +438,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
426 { 438 {
427 ITerrainChannel channel = loader.Value.LoadStream(stream); 439 ITerrainChannel channel = loader.Value.LoadStream(stream);
428 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement); 440 m_channel.Merge(channel, displacement, radianRotation, rotationDisplacement);
429 UpdateRevertMap(); 441 UpdateBakedMap();
430 } 442 }
431 catch(NotImplementedException) 443 catch(NotImplementedException)
432 { 444 {
@@ -506,12 +518,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
506 518
507 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients. 519 // Someone diddled terrain outside the normal code paths. Set the taintedness for all clients.
508 // ITerrainModule.TaintTerrain() 520 // ITerrainModule.TaintTerrain()
509 public void TaintTerrain() 521 public void TaintTerrain ()
510 { 522 {
511 lock(m_perClientPatchUpdates) 523 lock (m_perClientPatchUpdates)
512 { 524 {
513 // Set the flags for all clients so the tainted patches will be sent out 525 // Set the flags for all clients so the tainted patches will be sent out
514 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) 526 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
515 { 527 {
516 pups.SetAll(m_scene.Heightmap.GetTerrainData()); 528 pups.SetAll(m_scene.Heightmap.GetTerrainData());
517 } 529 }
@@ -521,13 +533,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
521 // ITerrainModule.PushTerrain() 533 // ITerrainModule.PushTerrain()
522 public void PushTerrain(IClientAPI pClient) 534 public void PushTerrain(IClientAPI pClient)
523 { 535 {
524 // If view distance based, set the modified patch bits and the frame event will send the updates
525 if (m_sendTerrainUpdatesByViewDistance) 536 if (m_sendTerrainUpdatesByViewDistance)
526 { 537 {
527 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId); 538 ScenePresence presence = m_scene.GetScenePresence(pClient.AgentId);
528 if (presence != null) 539 if (presence != null)
529 { 540 {
530 lock(m_perClientPatchUpdates) 541 lock (m_perClientPatchUpdates)
531 { 542 {
532 PatchUpdates pups; 543 PatchUpdates pups;
533 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups)) 544 if (!m_perClientPatchUpdates.TryGetValue(pClient.AgentId, out pups))
@@ -536,7 +547,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
536 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence); 547 pups = new PatchUpdates(m_scene.Heightmap.GetTerrainData(), presence);
537 m_perClientPatchUpdates.Add(presence.UUID, pups); 548 m_perClientPatchUpdates.Add(presence.UUID, pups);
538 } 549 }
539 // By setting all to modified, the next update tick will send the patches
540 pups.SetAll(true); 550 pups.SetAll(true);
541 } 551 }
542 } 552 }
@@ -547,6 +557,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
547 pClient.SendLayerData(new float[10]); 557 pClient.SendLayerData(new float[10]);
548 } 558 }
549 } 559 }
560
550 #region Plugin Loading Methods 561 #region Plugin Loading Methods
551 562
552 private void LoadPlugins() 563 private void LoadPlugins()
@@ -636,7 +647,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
636 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere(); 647 m_painteffects[StandardTerrainEffects.Smooth] = new SmoothSphere();
637 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere(); 648 m_painteffects[StandardTerrainEffects.Noise] = new NoiseSphere();
638 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere(); 649 m_painteffects[StandardTerrainEffects.Flatten] = new FlattenSphere();
639 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_revert); 650 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_baked);
640 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere(); 651 m_painteffects[StandardTerrainEffects.Erode] = new ErodeSphere();
641 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere(); 652 m_painteffects[StandardTerrainEffects.Weather] = new WeatherSphere();
642 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere(); 653 m_painteffects[StandardTerrainEffects.Olsen] = new OlsenSphere();
@@ -647,9 +658,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
647 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea(); 658 m_floodeffects[StandardTerrainEffects.Smooth] = new SmoothArea();
648 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea(); 659 m_floodeffects[StandardTerrainEffects.Noise] = new NoiseArea();
649 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea(); 660 m_floodeffects[StandardTerrainEffects.Flatten] = new FlattenArea();
650 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_revert); 661 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_baked);
651 662
652 // Terrain Modifier operations 663 // Terrain Modifier operations
664
653 m_modifyOperations["min"] = new MinModifier(this); 665 m_modifyOperations["min"] = new MinModifier(this);
654 m_modifyOperations["max"] = new MaxModifier(this); 666 m_modifyOperations["max"] = new MaxModifier(this);
655 m_modifyOperations["raise"] = new RaiseModifier(this); 667 m_modifyOperations["raise"] = new RaiseModifier(this);
@@ -673,22 +685,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
673 } 685 }
674 686
675 /// <summary> 687 /// <summary>
676 /// Saves the current state of the region into the revert map buffer. 688 /// Saves the current state of the region into the baked map buffer.
689
677 /// </summary> 690 /// </summary>
678 public void UpdateRevertMap() 691 public void UpdateBakedMap()
679 { 692 {
680 /* 693 m_baked = m_channel.MakeCopy();
681 int x; 694 m_painteffects[StandardTerrainEffects.Revert] = new RevertSphere(m_baked);
682 for (x = 0; x < m_channel.Width; x++) 695 m_floodeffects[StandardTerrainEffects.Revert] = new RevertArea(m_baked);
683 {
684 int y;
685 for (y = 0; y < m_channel.Height; y++)
686 {
687 m_revert[x, y] = m_channel[x, y];
688 }
689 }
690 */
691 m_revert = m_channel.MakeCopy();
692 } 696 }
693 697
694 /// <summary> 698 /// <summary>
@@ -715,11 +719,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain
715 { 719 {
716 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY, 720 ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
717 fileWidth, fileHeight, 721 fileWidth, fileHeight,
718 (int)m_scene.RegionInfo.RegionSizeX, 722 (int) m_scene.RegionInfo.RegionSizeX,
719 (int)m_scene.RegionInfo.RegionSizeY); 723 (int) m_scene.RegionInfo.RegionSizeY);
720 m_scene.Heightmap = channel; 724 m_scene.Heightmap = channel;
721 m_channel = channel; 725 m_channel = channel;
722 UpdateRevertMap(); 726 UpdateBakedMap();
723 } 727 }
724 728
725 return; 729 return;
@@ -781,39 +785,54 @@ namespace OpenSim.Region.CoreModules.World.Terrain
781 m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave); 785 m_scene.RegionInfo.RegionName, filename, m_supportFileExtensionsForTileSave);
782 } 786 }
783 787
788
784 /// <summary> 789 /// <summary>
785 /// Called before processing of every simulation frame.
786 /// This is used to check to see of any of the terrain is tainted and, if so, schedule 790 /// This is used to check to see of any of the terrain is tainted and, if so, schedule
787 /// updates for all the presences. 791 /// updates for all the presences.
788 /// This also checks to see if there are updates that need to be sent for each presence. 792 /// This also checks to see if there are updates that need to be sent for each presence.
789 /// This is where the logic is to send terrain updates to clients. 793 /// This is where the logic is to send terrain updates to clients.
790 /// </summary> 794 /// </summary>
791 private void EventManager_OnFrame() 795 /// doing it async, since currently this is 2 heavy for heartbeat
796 private void EventManager_TerrainCheckUpdates()
792 { 797 {
793 TerrainData terrData = m_channel.GetTerrainData(); 798 Util.FireAndForget(
799 EventManager_TerrainCheckUpdatesAsync);
800 }
794 801
795 bool shouldTaint = false; 802 object TerrainCheckUpdatesLock = new object();
796 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 803
804 private void EventManager_TerrainCheckUpdatesAsync(object o)
805 {
806 // dont overlap execution
807 if(Monitor.TryEnter(TerrainCheckUpdatesLock))
797 { 808 {
798 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 809 // this needs fixing
810 TerrainData terrData = m_channel.GetTerrainData();
811
812 bool shouldTaint = false;
813 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
799 { 814 {
800 if (terrData.IsTaintedAt(x, y)) 815 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
801 { 816 {
802 // Found a patch that was modified. Push this flag into the clients. 817 if (terrData.IsTaintedAt(x, y,true))
803 SendToClients(terrData, x, y); 818 {
804 shouldTaint = true; 819 // Found a patch that was modified. Push this flag into the clients.
820 SendToClients(terrData, x, y);
821 shouldTaint = true;
822 }
805 } 823 }
806 } 824 }
807 }
808 825
809 // This event also causes changes to be sent to the clients 826 // This event also causes changes to be sent to the clients
810 CheckSendingPatchesToClients(); 827 CheckSendingPatchesToClients();
811 828
812 // If things changes, generate some events 829 // If things changes, generate some events
813 if (shouldTaint) 830 if (shouldTaint)
814 { 831 {
815 m_scene.EventManager.TriggerTerrainTainted(); 832 m_scene.EventManager.TriggerTerrainTainted();
816 m_tainted = true; 833 m_tainted = true;
834 }
835 Monitor.Exit(TerrainCheckUpdatesLock);
817 } 836 }
818 } 837 }
819 838
@@ -883,11 +902,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
883 presence.ControllingClient.OnLandUndo -= client_OnLandUndo; 902 presence.ControllingClient.OnLandUndo -= client_OnLandUndo;
884 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; 903 presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain;
885 } 904 }
886 905 lock (m_perClientPatchUpdates)
887 lock(m_perClientPatchUpdates)
888 m_perClientPatchUpdates.Remove(client); 906 m_perClientPatchUpdates.Remove(client);
889 } 907 }
890 908
891 /// <summary> 909 /// <summary>
892 /// Scan over changes in the terrain and limit height changes. This enforces the 910 /// Scan over changes in the terrain and limit height changes. This enforces the
893 /// non-estate owner limits on rate of terrain editting. 911 /// non-estate owner limits on rate of terrain editting.
@@ -898,12 +916,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
898 TerrainData terrData = m_channel.GetTerrainData(); 916 TerrainData terrData = m_channel.GetTerrainData();
899 917
900 bool wasLimited = false; 918 bool wasLimited = false;
901 for(int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) 919 for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize)
902 { 920 {
903 for(int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) 921 for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize)
904 { 922 {
905 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) 923 if (terrData.IsTaintedAt(x, y, false /* clearOnTest */))
906 { 924 {
907 // If we should respect the estate settings then 925 // If we should respect the estate settings then
908 // fixup and height deltas that don't respect them. 926 // fixup and height deltas that don't respect them.
909 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. 927 // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values.
@@ -926,13 +944,13 @@ namespace OpenSim.Region.CoreModules.World.Terrain
926 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; 944 float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit;
927 945
928 // loop through the height map for this patch and compare it against 946 // loop through the height map for this patch and compare it against
929 // the revert map 947 // the baked map
930 for(int x = xStart; x < xStart + Constants.TerrainPatchSize; x++) 948 for (int x = xStart; x < xStart + Constants.TerrainPatchSize; x++)
931 { 949 {
932 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) 950 for(int y = yStart; y < yStart + Constants.TerrainPatchSize; y++)
933 { 951 {
934 float requestedHeight = terrData[x, y]; 952 float requestedHeight = terrData[x, y];
935 float bakedHeight = (float)m_revert[x, y]; 953 float bakedHeight = (float)m_baked[x, y];
936 float requestedDelta = requestedHeight - bakedHeight; 954 float requestedDelta = requestedHeight - bakedHeight;
937 955
938 if (requestedDelta > maxDelta) 956 if (requestedDelta > maxDelta)
@@ -953,15 +971,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
953 971
954 private void client_OnLandUndo(IClientAPI client) 972 private void client_OnLandUndo(IClientAPI client)
955 { 973 {
956 lock(m_undo)
957 {
958 if (m_undo.Count > 0)
959 {
960 LandUndoState goback = m_undo.Pop();
961 if (goback != null)
962 goback.PlaybackState();
963 }
964 }
965 } 974 }
966 975
967 /// <summary> 976 /// <summary>
@@ -975,19 +984,19 @@ namespace OpenSim.Region.CoreModules.World.Terrain
975 if (m_sendTerrainUpdatesByViewDistance) 984 if (m_sendTerrainUpdatesByViewDistance)
976 { 985 {
977 // Add that this patch needs to be sent to the accounting for each client. 986 // Add that this patch needs to be sent to the accounting for each client.
978 lock(m_perClientPatchUpdates) 987 lock (m_perClientPatchUpdates)
979 { 988 {
980 m_scene.ForEachScenePresence(presence => 989 m_scene.ForEachScenePresence(presence =>
981 {
982 PatchUpdates thisClientUpdates;
983 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
984 { 990 {
985 // There is a ScenePresence without a send patch map. Create one. 991 PatchUpdates thisClientUpdates;
986 thisClientUpdates = new PatchUpdates(terrData, presence); 992 if (!m_perClientPatchUpdates.TryGetValue(presence.UUID, out thisClientUpdates))
987 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates); 993 {
994 // There is a ScenePresence without a send patch map. Create one.
995 thisClientUpdates = new PatchUpdates(terrData, presence);
996 m_perClientPatchUpdates.Add(presence.UUID, thisClientUpdates);
997 }
998 thisClientUpdates.SetByXY(x, y, true);
988 } 999 }
989 thisClientUpdates.SetByXY(x, y, true);
990 }
991 ); 1000 );
992 } 1001 }
993 } 1002 }
@@ -998,7 +1007,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
998 //float[] heightMap = terrData.GetFloatsSerialized(); 1007 //float[] heightMap = terrData.GetFloatsSerialized();
999 float[] heightMap = new float[10]; 1008 float[] heightMap = new float[10];
1000 m_scene.ForEachClient( 1009 m_scene.ForEachClient(
1001 delegate(IClientAPI controller) 1010 delegate (IClientAPI controller)
1002 { 1011 {
1003 controller.SendLayerData(x / Constants.TerrainPatchSize, 1012 controller.SendLayerData(x / Constants.TerrainPatchSize,
1004 y / Constants.TerrainPatchSize, 1013 y / Constants.TerrainPatchSize,
@@ -1013,14 +1022,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1013 public int PatchX; 1022 public int PatchX;
1014 public int PatchY; 1023 public int PatchY;
1015 public float Dist; 1024 public float Dist;
1016
1017 public PatchesToSend(int pX, int pY, float pDist) 1025 public PatchesToSend(int pX, int pY, float pDist)
1018 { 1026 {
1019 PatchX = pX; 1027 PatchX = pX;
1020 PatchY = pY; 1028 PatchY = pY;
1021 Dist = pDist; 1029 Dist = pDist;
1022 } 1030 }
1023
1024 public int CompareTo(PatchesToSend other) 1031 public int CompareTo(PatchesToSend other)
1025 { 1032 {
1026 return Dist.CompareTo(other.Dist); 1033 return Dist.CompareTo(other.Dist);
@@ -1029,119 +1036,224 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1029 1036
1030 // Called each frame time to see if there are any patches to send to any of the 1037 // Called each frame time to see if there are any patches to send to any of the
1031 // ScenePresences. 1038 // ScenePresences.
1032 // We know this is only called if we are doing view distance patch sending so some
1033 // tests are not made.
1034 // Loop through all the per-client info and send any patches necessary. 1039 // Loop through all the per-client info and send any patches necessary.
1035 private void CheckSendingPatchesToClients() 1040 private void CheckSendingPatchesToClients()
1036 { 1041 {
1037 lock(m_perClientPatchUpdates) 1042 lock (m_perClientPatchUpdates)
1038 { 1043 {
1039 foreach(PatchUpdates pups in m_perClientPatchUpdates.Values) 1044 foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
1040 { 1045 {
1046 if(pups.Presence.IsDeleted)
1047 continue;
1048
1049 // limit rate acording to udp land queue state
1050 if (!pups.Presence.ControllingClient.CanSendLayerData())
1051 continue;
1052
1041 if (pups.HasUpdates()) 1053 if (pups.HasUpdates())
1042 { 1054 {
1043 // There is something that could be sent to this client. 1055 if (m_sendTerrainUpdatesByViewDistance)
1044 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1045 if (toSend.Count > 0)
1046 { 1056 {
1047 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}", 1057 // There is something that could be sent to this client.
1048 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName); 1058 List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
1049 // Sort the patches to send by the distance from the presence 1059 if (toSend.Count > 0)
1050 toSend.Sort();
1051 /* old way that sent individual patches
1052 foreach (PatchesToSend pts in toSend)
1053 { 1060 {
1054 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null); 1061 // m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
1055 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land); 1062 // LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
1056 } 1063 // Sort the patches to send by the distance from the presence
1057 */ 1064 toSend.Sort();
1058 1065 /*
1059 // new way that sends all patches to the protocol so they can be sent in one block 1066 foreach (PatchesToSend pts in toSend)
1060 int[] xPieces = new int[toSend.Count]; 1067 {
1061 int[] yPieces = new int[toSend.Count]; 1068 pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
1062 float[] patchPieces = new float[toSend.Count * 2]; 1069 // presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
1063 int pieceIndex = 0; 1070 }
1064 foreach(PatchesToSend pts in toSend) 1071 */
1065 { 1072
1066 patchPieces[pieceIndex++] = pts.PatchX; 1073 int[] xPieces = new int[toSend.Count];
1067 patchPieces[pieceIndex++] = pts.PatchY; 1074 int[] yPieces = new int[toSend.Count];
1075 float[] patchPieces = new float[toSend.Count * 2];
1076 int pieceIndex = 0;
1077 foreach (PatchesToSend pts in toSend)
1078 {
1079 patchPieces[pieceIndex++] = pts.PatchX;
1080 patchPieces[pieceIndex++] = pts.PatchY;
1081 }
1082 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces);
1068 } 1083 }
1069 pups.Presence.ControllingClient.SendLayerData(-toSend.Count, 0, patchPieces); 1084 if (pups.sendAll && toSend.Count < 1024)
1085 SendAllModifiedPatchs(pups);
1070 } 1086 }
1087 else
1088 SendAllModifiedPatchs(pups);
1071 } 1089 }
1072 } 1090 }
1073 } 1091 }
1074 } 1092 }
1093 private void SendAllModifiedPatchs(PatchUpdates pups)
1094 {
1095 if (!pups.sendAll) // sanity
1096 return;
1097
1098 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1099 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1100
1101 if (pups.sendAllcurrentX >= limitX && pups.sendAllcurrentY >= limitY)
1102 {
1103 pups.sendAll = false;
1104 pups.sendAllcurrentX = 0;
1105 pups.sendAllcurrentY = 0;
1106 return;
1107 }
1108
1109 int npatchs = 0;
1110 List<PatchesToSend> patchs = new List<PatchesToSend>();
1111 int x = pups.sendAllcurrentX;
1112 int y = pups.sendAllcurrentY;
1113 // send it in the order viewer draws it
1114 // even if not best for memory scan
1115 for (; y < limitY; y++)
1116 {
1117 for (; x < limitX; x++)
1118 {
1119 if (pups.GetByPatch(x, y))
1120 {
1121 pups.SetByPatch(x, y, false);
1122 patchs.Add(new PatchesToSend(x, y, 0));
1123 if (++npatchs >= 128)
1124 {
1125 x++;
1126 break;
1127 }
1128 }
1129 }
1130 if (npatchs >= 128)
1131 break;
1132 x = 0;
1133 }
1134
1135 if (x >= limitX && y >= limitY)
1136 {
1137 pups.sendAll = false;
1138 pups.sendAllcurrentX = 0;
1139 pups.sendAllcurrentY = 0;
1140 }
1141 else
1142 {
1143 pups.sendAllcurrentX = x;
1144 pups.sendAllcurrentY = y;
1145 }
1146
1147 npatchs = patchs.Count;
1148 if (npatchs > 0)
1149 {
1150 int[] xPieces = new int[npatchs];
1151 int[] yPieces = new int[npatchs];
1152 float[] patchPieces = new float[npatchs * 2];
1153 int pieceIndex = 0;
1154 foreach (PatchesToSend pts in patchs)
1155 {
1156 patchPieces[pieceIndex++] = pts.PatchX;
1157 patchPieces[pieceIndex++] = pts.PatchY;
1158 }
1159 pups.Presence.ControllingClient.SendLayerData(-npatchs, 0, patchPieces);
1160 }
1161 }
1075 1162
1076 // Compute a list of modified patches that are within our view distance.
1077 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups) 1163 private List<PatchesToSend> GetModifiedPatchesInViewDistance(PatchUpdates pups)
1078 { 1164 {
1079 List<PatchesToSend> ret = new List<PatchesToSend>(); 1165 List<PatchesToSend> ret = new List<PatchesToSend>();
1080 1166
1167 int npatchs = 0;
1168
1081 ScenePresence presence = pups.Presence; 1169 ScenePresence presence = pups.Presence;
1082 if (presence == null) 1170 if (presence == null)
1083 return ret; 1171 return ret;
1084 1172
1085 Vector3 presencePos = presence.AbsolutePosition; 1173 float minz = presence.AbsolutePosition.Z;
1086 1174 if (presence.CameraPosition.Z < minz)
1087 // Before this distance check, the whole region just showed up. Adding the distance 1175 minz = presence.CameraPosition.Z;
1088 // check causes different things to happen for the current and adjacent regions. 1176
1089 // So, to keep legacy views, if the region is legacy sized, don't do distance check. 1177 // this limit should be max terrainheight + max draw
1090 bool isLegacySizedRegion = pups.Terrain.SizeX == Constants.RegionSize && pups.Terrain.SizeY == Constants.RegionSize; 1178 if (minz > 1500f)
1091 bool shouldCheckViewDistance = m_sendTerrainUpdatesByViewDistance && !isLegacySizedRegion; 1179 return ret;
1092 1180
1093 int startX = 0; 1181 int DrawDistance = (int)presence.DrawDistance;
1094 int endX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize; 1182
1095 int startY = 0; 1183 DrawDistance = DrawDistance / Constants.TerrainPatchSize;
1096 int endY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize; 1184
1097 1185 int testposX;
1098 // The following only reduces the size of area scanned for updates. Only significant for very large varregions. 1186 int testposY;
1099 if (shouldCheckViewDistance) 1187
1100 { 1188 if (Math.Abs(presence.AbsolutePosition.X - presence.CameraPosition.X) > 30
1101 // Compute the area of patches within our draw distance 1189 || Math.Abs(presence.AbsolutePosition.Y - presence.CameraPosition.Y) > 30)
1102 startX = (((int)(presencePos.X - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; 1190 {
1103 startX = Math.Max(startX, 0); 1191 testposX = (int)presence.CameraPosition.X / Constants.TerrainPatchSize;
1104 startX = Math.Min(startX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); 1192 testposY = (int)presence.CameraPosition.Y / Constants.TerrainPatchSize;
1105 startY = (((int)(presencePos.Y - presence.DrawDistance)) / Constants.TerrainPatchSize) - 2; 1193 }
1106 startY = Math.Max(startY, 0); 1194 else
1107 startY = Math.Min(startY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); 1195 {
1108 endX = (((int)(presencePos.X + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; 1196 testposX = (int)presence.AbsolutePosition.X / Constants.TerrainPatchSize;
1109 endX = Math.Max(endX, 0); 1197 testposY = (int)presence.AbsolutePosition.Y / Constants.TerrainPatchSize;
1110 endX = Math.Min(endX, (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize); 1198 }
1111 endY = (((int)(presencePos.Y + presence.DrawDistance)) / Constants.TerrainPatchSize) + 2; 1199 int limitX = (int)m_scene.RegionInfo.RegionSizeX / Constants.TerrainPatchSize;
1112 endY = Math.Max(endY, 0); 1200 int limitY = (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize;
1113 endY = Math.Min(endY, (int)m_scene.RegionInfo.RegionSizeY / Constants.TerrainPatchSize); 1201
1114 } 1202 // Compute the area of patches within our draw distance
1115 1203 int startX = testposX - DrawDistance;
1116 // m_log.DebugFormat("{0} GetModifiedPatchesInViewDistance. rName={1}, ddist={2}, apos={3}, cpos={4}, isChild={5}, start=<{6},{7}>, end=<{8},{9}>", 1204 if (startX < 0)
1117 // LogHeader, m_scene.RegionInfo.RegionName, 1205 startX = 0;
1118 // presence.DrawDistance, presencePos, presence.CameraPosition, 1206 else if (startX >= limitX)
1119 // isLegacySizeChildRegion, 1207 startX = limitX - 1;
1120 // startX, startY, endX, endY); 1208
1121 for(int x = startX; x < endX; x++) 1209 int startY = testposY - DrawDistance;
1122 { 1210 if (startY < 0)
1123 for(int y = startY; y < endY; y++) 1211 startY = 0;
1212 else if (startY >= limitY)
1213 startY = limitY - 1;
1214
1215 int endX = testposX + DrawDistance;
1216 if (endX < 0)
1217 endX = 0;
1218 else if (endX > limitX)
1219 endX = limitX;
1220
1221 int endY = testposY + DrawDistance;
1222 if (endY < 0)
1223 endY = 0;
1224 else if (endY > limitY)
1225 endY = limitY;
1226
1227 int distx;
1228 int disty;
1229 int distsq;
1230
1231 DrawDistance *= DrawDistance;
1232
1233 for (int x = startX; x < endX; x++)
1234 {
1235 for (int y = startY; y < endY; y++)
1124 { 1236 {
1125 //Need to make sure we don't send the same ones over and over
1126 Vector3 patchPos = new Vector3(x * Constants.TerrainPatchSize, y * Constants.TerrainPatchSize, presencePos.Z);
1127 if (pups.GetByPatch(x, y)) 1237 if (pups.GetByPatch(x, y))
1128 { 1238 {
1129 //Check which has less distance, camera or avatar position, both have to be done. 1239 distx = x - testposX;
1130 //Its not a radius, its a diameter and we add 50 so that it doesn't look like it cuts off 1240 disty = y - testposY;
1131 if (!shouldCheckViewDistance 1241 distsq = distx * distx + disty * disty;
1132 || Util.DistanceLessThan(presencePos, patchPos, presence.DrawDistance + 50) 1242 if (distsq < DrawDistance)
1133 || Util.DistanceLessThan(presence.CameraPosition, patchPos, presence.DrawDistance + 50))
1134 { 1243 {
1135 //They can see it, send it to them
1136 pups.SetByPatch(x, y, false); 1244 pups.SetByPatch(x, y, false);
1137 float dist = Vector3.DistanceSquared(presencePos, patchPos); 1245 ret.Add(new PatchesToSend(x, y, (float)distsq));
1138 ret.Add(new PatchesToSend(x, y, dist)); 1246 if (npatchs++ > 1024)
1247 {
1248 y = endY;
1249 x = endX;
1250 }
1139 } 1251 }
1140 } 1252 }
1141 } 1253 }
1142 } 1254 }
1143 return ret; 1255 return ret;
1144 } 1256 }
1145 1257
1146 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action, 1258 private void client_OnModifyTerrain(UUID user, float height, float seconds, byte size, byte action,
1147 float north, float west, float south, float east, UUID agentId) 1259 float north, float west, float south, float east, UUID agentId)
@@ -1161,31 +1273,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1161 int zx = (int)(west + 0.5); 1273 int zx = (int)(west + 0.5);
1162 int zy = (int)(north + 0.5); 1274 int zy = (int)(north + 0.5);
1163 1275
1164 int dx; 1276 int startX = zx - n;
1165 for(dx=-n; dx<=n; dx++) 1277 if (startX < 0)
1278 startX = 0;
1279
1280 int startY = zy - n;
1281 if (startY < 0)
1282 startY = 0;
1283
1284 int endX = zx + n;
1285 if (endX >= m_channel.Width)
1286 endX = m_channel.Width - 1;
1287 int endY = zy + n;
1288 if (endY >= m_channel.Height)
1289 endY = m_channel.Height - 1;
1290
1291 int x, y;
1292
1293 for (x = startX; x <= endX; x++)
1166 { 1294 {
1167 int dy; 1295 for (y = startY; y <= endY; y++)
1168 for(dy=-n; dy<=n; dy++)
1169 { 1296 {
1170 int x = zx + dx; 1297 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1171 int y = zy + dy;
1172 if (x >= 0 && y >= 0 && x < m_channel.Width && y < m_channel.Height)
1173 { 1298 {
1174 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0))) 1299 allowMask[x, y] = true;
1175 { 1300 allowed = true;
1176 allowMask[x, y] = true;
1177 allowed = true;
1178 }
1179 } 1301 }
1180 } 1302 }
1181 } 1303 }
1182 if (allowed) 1304 if (allowed)
1183 { 1305 {
1184 StoreUndoState(); 1306 StoreUndoState();
1185 m_painteffects[(StandardTerrainEffects)action].PaintEffect( 1307 m_painteffects[(StandardTerrainEffects) action].PaintEffect(
1186 m_channel, allowMask, west, south, height, size, seconds); 1308 m_channel, allowMask, west, south, height, size, seconds,
1309 startX, endX, startY, endY);
1187 1310
1188 //revert changes outside estate limits 1311 //block changes outside estate limits
1189 if (!god) 1312 if (!god)
1190 EnforceEstateLimits(); 1313 EnforceEstateLimits();
1191 } 1314 }
@@ -1202,22 +1325,42 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1202 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height]; 1325 bool[,] fillArea = new bool[m_channel.Width, m_channel.Height];
1203 fillArea.Initialize(); 1326 fillArea.Initialize();
1204 1327
1205 int x; 1328 int startX = (int)west;
1206 for(x = 0; x < m_channel.Width; x++) 1329 int startY = (int)south;
1330 int endX = (int)east;
1331 int endY = (int)north;
1332
1333 if (startX < 0)
1334 startX = 0;
1335 else if (startX >= m_channel.Width)
1336 startX = m_channel.Width - 1;
1337
1338 if (endX < 0)
1339 endX = 0;
1340 else if (endX >= m_channel.Width)
1341 endX = m_channel.Width - 1;
1342
1343 if (startY < 0)
1344 startY = 0;
1345 else if (startY >= m_channel.Height)
1346 startY = m_channel.Height - 1;
1347
1348 if (endY < 0)
1349 endY = 0;
1350 else if (endY >= m_channel.Height)
1351 endY = m_channel.Height - 1;
1352
1353
1354 int x, y;
1355
1356 for (x = startX; x <= endX; x++)
1207 { 1357 {
1208 int y; 1358 for (y = startY; y <= endY; y++)
1209 for(y = 0; y < m_channel.Height; y++)
1210 { 1359 {
1211 if (x < east && x > west) 1360 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1212 { 1361 {
1213 if (y < north && y > south) 1362 fillArea[x, y] = true;
1214 { 1363 allowed = true;
1215 if (m_scene.Permissions.CanTerraformLand(agentId, new Vector3(x, y, 0)))
1216 {
1217 fillArea[x, y] = true;
1218 allowed = true;
1219 }
1220 }
1221 } 1364 }
1222 } 1365 }
1223 } 1366 }
@@ -1225,9 +1368,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1225 if (allowed) 1368 if (allowed)
1226 { 1369 {
1227 StoreUndoState(); 1370 StoreUndoState();
1228 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size); 1371 m_floodeffects[(StandardTerrainEffects)action].FloodEffect(m_channel, fillArea, size,
1372 startX, endX, startY, endY);
1229 1373
1230 //revert changes outside estate limits 1374 //block changes outside estate limits
1231 if (!god) 1375 if (!god)
1232 EnforceEstateLimits(); 1376 EnforceEstateLimits();
1233 } 1377 }
@@ -1260,37 +1404,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1260 1404
1261 private void StoreUndoState() 1405 private void StoreUndoState()
1262 { 1406 {
1263 lock(m_undo)
1264 {
1265 if (m_undo.Count > 0)
1266 {
1267 LandUndoState last = m_undo.Peek();
1268 if (last != null)
1269 {
1270 if (last.Compare(m_channel))
1271 return;
1272 }
1273 }
1274
1275 LandUndoState nUndo = new LandUndoState(this, m_channel);
1276 m_undo.Push(nUndo);
1277 }
1278 } 1407 }
1279 1408
1280 #region Console Commands 1409 #region Console Commands
1281 1410
1282 private void InterfaceLoadFile(Object[] args) 1411 private void InterfaceLoadFile(Object[] args)
1283 { 1412 {
1284 LoadFromFile((string)args[0]); 1413 LoadFromFile((string) args[0]);
1285 } 1414 }
1286 1415
1287 private void InterfaceLoadTileFile(Object[] args) 1416 private void InterfaceLoadTileFile(Object[] args)
1288 { 1417 {
1289 LoadFromFile((string)args[0], 1418 LoadFromFile((string) args[0],
1290 (int)args[1], 1419 (int) args[1],
1291 (int)args[2], 1420 (int) args[2],
1292 (int)args[3], 1421 (int) args[3],
1293 (int)args[4]); 1422 (int) args[4]);
1294 } 1423 }
1295 1424
1296 private void InterfaceSaveFile(Object[] args) 1425 private void InterfaceSaveFile(Object[] args)
@@ -1309,15 +1438,15 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1309 1438
1310 private void InterfaceBakeTerrain(Object[] args) 1439 private void InterfaceBakeTerrain(Object[] args)
1311 { 1440 {
1312 UpdateRevertMap(); 1441 UpdateBakedMap();
1313 } 1442 }
1314 1443
1315 private void InterfaceRevertTerrain(Object[] args) 1444 private void InterfaceRevertTerrain(Object[] args)
1316 { 1445 {
1317 int x, y; 1446 int x, y;
1318 for(x = 0; x < m_channel.Width; x++) 1447 for (x = 0; x < m_channel.Width; x++)
1319 for(y = 0; y < m_channel.Height; y++) 1448 for (y = 0; y < m_channel.Height; y++)
1320 m_channel[x, y] = m_revert[x, y]; 1449 m_channel[x, y] = m_baked[x, y];
1321 1450
1322 } 1451 }
1323 1452
@@ -1327,9 +1456,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1327 1456
1328 if (direction.ToLower().StartsWith("y")) 1457 if (direction.ToLower().StartsWith("y"))
1329 { 1458 {
1330 for(int x = 0; x < m_channel.Width; x++) 1459 for (int x = 0; x < m_channel.Width; x++)
1331 { 1460 {
1332 for(int y = 0; y < m_channel.Height / 2; y++) 1461 for (int y = 0; y < m_channel.Height / 2; y++)
1333 { 1462 {
1334 double height = m_channel[x, y]; 1463 double height = m_channel[x, y];
1335 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y]; 1464 double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
@@ -1341,9 +1470,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1341 } 1470 }
1342 else if (direction.ToLower().StartsWith("x")) 1471 else if (direction.ToLower().StartsWith("x"))
1343 { 1472 {
1344 for(int y = 0; y < m_channel.Height; y++) 1473 for (int y = 0; y < m_channel.Height; y++)
1345 { 1474 {
1346 for(int x = 0; x < m_channel.Width / 2; x++) 1475 for (int x = 0; x < m_channel.Width / 2; x++)
1347 { 1476 {
1348 double height = m_channel[x, y]; 1477 double height = m_channel[x, y];
1349 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y]; 1478 double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
@@ -1415,50 +1544,57 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1415 } 1544 }
1416 1545
1417 } 1546 }
1418
1419 } 1547 }
1420 1548
1421 private void InterfaceElevateTerrain(Object[] args) 1549 private void InterfaceElevateTerrain(Object[] args)
1422 { 1550 {
1551 double val = (double)args[0];
1552
1423 int x, y; 1553 int x, y;
1424 for(x = 0; x < m_channel.Width; x++) 1554 for (x = 0; x < m_channel.Width; x++)
1425 for(y = 0; y < m_channel.Height; y++) 1555 for (y = 0; y < m_channel.Height; y++)
1426 m_channel[x, y] += (double)args[0]; 1556 m_channel[x, y] += val;
1427 } 1557 }
1428 1558
1429 private void InterfaceMultiplyTerrain(Object[] args) 1559 private void InterfaceMultiplyTerrain(Object[] args)
1430 { 1560 {
1431 int x, y; 1561 int x, y;
1432 for(x = 0; x < m_channel.Width; x++) 1562 double val = (double)args[0];
1433 for(y = 0; y < m_channel.Height; y++) 1563
1434 m_channel[x, y] *= (double)args[0]; 1564 for (x = 0; x < m_channel.Width; x++)
1565 for (y = 0; y < m_channel.Height; y++)
1566 m_channel[x, y] *= val;
1435 } 1567 }
1436 1568
1437 private void InterfaceLowerTerrain(Object[] args) 1569 private void InterfaceLowerTerrain(Object[] args)
1438 { 1570 {
1439 int x, y; 1571 int x, y;
1440 for(x = 0; x < m_channel.Width; x++) 1572 double val = (double)args[0];
1441 for(y = 0; y < m_channel.Height; y++) 1573
1442 m_channel[x, y] -= (double)args[0]; 1574 for (x = 0; x < m_channel.Width; x++)
1575 for (y = 0; y < m_channel.Height; y++)
1576 m_channel[x, y] -= val;
1443 } 1577 }
1444 1578
1445 public void InterfaceFillTerrain(Object[] args) 1579 public void InterfaceFillTerrain(Object[] args)
1446 { 1580 {
1447 int x, y; 1581 int x, y;
1582 double val = (double)args[0];
1448 1583
1449 for(x = 0; x < m_channel.Width; x++) 1584 for (x = 0; x < m_channel.Width; x++)
1450 for(y = 0; y < m_channel.Height; y++) 1585 for (y = 0; y < m_channel.Height; y++)
1451 m_channel[x, y] = (double)args[0]; 1586 m_channel[x, y] = val;
1452 } 1587 }
1453 1588
1454 private void InterfaceMinTerrain(Object[] args) 1589 private void InterfaceMinTerrain(Object[] args)
1455 { 1590 {
1456 int x, y; 1591 int x, y;
1457 for(x = 0; x < m_channel.Width; x++) 1592 double val = (double)args[0];
1593 for (x = 0; x < m_channel.Width; x++)
1458 { 1594 {
1459 for(y = 0; y < m_channel.Height; y++) 1595 for(y = 0; y < m_channel.Height; y++)
1460 { 1596 {
1461 m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); 1597 m_channel[x, y] = Math.Max(val, m_channel[x, y]);
1462 } 1598 }
1463 } 1599 }
1464 } 1600 }
@@ -1466,11 +1602,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1466 private void InterfaceMaxTerrain(Object[] args) 1602 private void InterfaceMaxTerrain(Object[] args)
1467 { 1603 {
1468 int x, y; 1604 int x, y;
1469 for(x = 0; x < m_channel.Width; x++) 1605 double val = (double)args[0];
1606 for (x = 0; x < m_channel.Width; x++)
1470 { 1607 {
1471 for(y = 0; y < m_channel.Height; y++) 1608 for(y = 0; y < m_channel.Height; y++)
1472 { 1609 {
1473 m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); 1610 m_channel[x, y] = Math.Min(val, m_channel[x, y]);
1474 } 1611 }
1475 } 1612 }
1476 } 1613 }
@@ -1620,9 +1757,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1620 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double"); 1757 multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");
1621 1758
1622 Command bakeRegionCommand = 1759 Command bakeRegionCommand =
1623 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions revert map."); 1760 new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions baked map.");
1624 Command revertRegionCommand = 1761 Command revertRegionCommand =
1625 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap."); 1762 new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the baked map terrain into the regions heightmap.");
1626 1763
1627 Command flipCommand = 1764 Command flipCommand =
1628 new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis"); 1765 new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis");
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index 29e80ef..b209b33 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -60,7 +60,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
60 TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize); 60 TerrainChannel map = new TerrainChannel((int)Constants.RegionSize, (int)Constants.RegionSize);
61 ITerrainPaintableEffect effect = new RaiseSphere(); 61 ITerrainPaintableEffect effect = new RaiseSphere();
62 62
63 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0); 63 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0,
64 0, midRegion - 1,0, (int)Constants.RegionSize -1);
64 Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128)."); 65 Assert.That(map[127, midRegion] > 0.0, "Raise brush should raising value at this point (127,128).");
65 Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128)."); 66 Assert.That(map[125, midRegion] > 0.0, "Raise brush should raising value at this point (124,128).");
66 Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128)."); 67 Assert.That(map[120, midRegion] == 0.0, "Raise brush should not change value at this point (120,128).");
@@ -79,7 +80,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain.Tests
79 } 80 }
80 effect = new LowerSphere(); 81 effect = new LowerSphere();
81 82
82 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0); 83 effect.PaintEffect(map, allowMask, midRegion, midRegion, -1.0, 2, 6.0,
84 0, (int)Constants.RegionSize -1,0, (int)Constants.RegionSize -1);
83 Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128)."); 85 Assert.That(map[127, midRegion] >= 0.0, "Lower should not lowering value below 0.0 at this point (127,128).");
84 Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128)."); 86 Assert.That(map[127, midRegion] == 0.0, "Lower brush should lowering value to 0.0 at this point (127,128).");
85 Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128)."); 87 Assert.That(map[125, midRegion] < 1.0, "Lower brush should lowering value at this point (124,128).");
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
index 9534ad3..4719ba3 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/TerrainSplat.cs
@@ -79,6 +79,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
79 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting 79 /// <remarks>Based on the algorithm described at http://opensimulator.org/wiki/Terrain_Splatting
80 /// Note we create a 256x256 dimension texture even if the actual terrain is larger. 80 /// Note we create a 256x256 dimension texture even if the actual terrain is larger.
81 /// </remarks> 81 /// </remarks>
82
82 public static Bitmap Splat(ITerrainChannel terrain, 83 public static Bitmap Splat(ITerrainChannel terrain,
83 UUID[] textureIDs, float[] startHeights, float[] heightRanges, 84 UUID[] textureIDs, float[] startHeights, float[] heightRanges,
84 Vector3d regionPosition, IAssetService assetService, bool textureTerrain) 85 Vector3d regionPosition, IAssetService assetService, bool textureTerrain)
@@ -129,8 +130,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
129 asset = assetService.Get(textureIDs[i].ToString()); 130 asset = assetService.Get(textureIDs[i].ToString());
130 if (asset != null) 131 if (asset != null)
131 { 132 {
132// m_log.DebugFormat( 133 // m_log.DebugFormat(
133// "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID); 134 // "[TERRAIN SPLAT]: Got cached original JPEG2000 terrain texture {0} {1}", i, asset.ID);
134 135
135 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); } 136 try { detailTexture[i] = (Bitmap)CSJ2K.J2kImage.FromBytes(asset.Data); }
136 catch (Exception ex) 137 catch (Exception ex)
@@ -140,7 +141,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
140 } 141 }
141 142
142 if (detailTexture[i] != null) 143 if (detailTexture[i] != null)
143 { 144 {
144 // Make sure this texture is the correct size, otherwise resize 145 // Make sure this texture is the correct size, otherwise resize
145 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256) 146 if (detailTexture[i].Width != 256 || detailTexture[i].Height != 256)
146 { 147 {
@@ -352,7 +353,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
352 b.Dispose(); 353 b.Dispose();
353 return result; 354 return result;
354 } 355 }
355
356 public static Bitmap SplatSimple(float[] heightmap) 356 public static Bitmap SplatSimple(float[] heightmap)
357 { 357 {
358 const float BASE_HSV_H = 93f / 360f; 358 const float BASE_HSV_H = 93f / 360f;
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 5f2534b..443eee1 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -80,6 +80,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
80 80
81 private bool m_Enabled = false; 81 private bool m_Enabled = false;
82 82
83 private Bitmap lastImage = null;
84 private DateTime lastImageTime = DateTime.MinValue;
85
83 #region Region Module interface 86 #region Region Module interface
84 87
85 public void Initialise(IConfigSource source) 88 public void Initialise(IConfigSource source)
@@ -118,14 +121,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
118 121
119 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 122 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
120 if (renderers.Count > 0) 123 if (renderers.Count > 0)
121 { 124 m_log.Info("[MAPTILE]: Loaded prim mesher " + renderers[0]);
122 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
123 m_log.DebugFormat("[WARP 3D IMAGE MODULE]: Loaded prim mesher {0}", m_primMesher);
124 }
125 else 125 else
126 { 126 m_log.Info("[MAPTILE]: No prim mesher loaded, prim rendering will be disabled");
127 m_log.Debug("[WARP 3D IMAGE MODULE]: No prim mesher loaded, prim rendering will be disabled");
128 }
129 127
130 m_scene.RegisterModuleInterface<IMapImageGenerator>(this); 128 m_scene.RegisterModuleInterface<IMapImageGenerator>(this);
131 } 129 }
@@ -158,18 +156,36 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
158 156
159 public Bitmap CreateMapTile() 157 public Bitmap CreateMapTile()
160 { 158 {
161 // Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); 159 /* this must be on all map, not just its image
162 // Camera above the middle of the region 160 if ((DateTime.Now - lastImageTime).TotalSeconds < 3600)
161 {
162 return (Bitmap)lastImage.Clone();
163 }
164 */
165
166 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
167 if (renderers.Count > 0)
168 {
169 m_primMesher = RenderingLoader.LoadRenderer(renderers[0]);
170 }
171
163 Vector3 camPos = new Vector3( 172 Vector3 camPos = new Vector3(
164 m_scene.RegionInfo.RegionSizeX/2 - 0.5f, 173 m_scene.RegionInfo.RegionSizeX / 2 - 0.5f,
165 m_scene.RegionInfo.RegionSizeY/2 - 0.5f, 174 m_scene.RegionInfo.RegionSizeY / 2 - 0.5f,
166 221.7025033688163f); 175 221.7025033688163f);
167 // Viewport viewing down onto the region 176 // Viewport viewing down onto the region
168 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, 177 Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f,
169 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY, 178 (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY,
170 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY ); 179 (float)m_scene.RegionInfo.RegionSizeX, (float)m_scene.RegionInfo.RegionSizeY);
171 // Fill the viewport and return the image 180
172 return CreateMapTile(viewport, false); 181 Bitmap tile = CreateMapTile(viewport, false);
182 m_primMesher = null;
183 return tile;
184/*
185 lastImage = tile;
186 lastImageTime = DateTime.Now;
187 return (Bitmap)lastImage.Clone();
188 */
173 } 189 }
174 190
175 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) 191 public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures)
@@ -285,9 +301,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
285 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight; 301 float waterHeight = (float)m_scene.RegionInfo.RegionSettings.WaterHeight;
286 302
287 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f); 303 renderer.AddPlane("Water", m_scene.RegionInfo.RegionSizeX * 0.5f);
288 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX/2 - 0.5f, 304 renderer.Scene.sceneobject("Water").setPos(m_scene.RegionInfo.RegionSizeX / 2 - 0.5f,
289 waterHeight, 305 waterHeight,
290 m_scene.RegionInfo.RegionSizeY/2 - 0.5f ); 306 m_scene.RegionInfo.RegionSizeY / 2 - 0.5f);
291 307
292 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR)); 308 warp_Material waterColorMaterial = new warp_Material(ConvertColor(WATER_COLOR));
293 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif 309 waterColorMaterial.setReflectivity(0); // match water color with standard map module thanks lkalif
@@ -316,7 +332,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
316 warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]); 332 warp_Vector pos = ConvertVector(x, y, (float)terrain[(int)x, (int)y]);
317 obj.addVertex(new warp_Vertex(pos, 333 obj.addVertex(new warp_Vertex(pos,
318 x / (float)m_scene.RegionInfo.RegionSizeX, 334 x / (float)m_scene.RegionInfo.RegionSizeX,
319 (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY) ); 335 (((float)m_scene.RegionInfo.RegionSizeY) - y) / m_scene.RegionInfo.RegionSizeY));
320 } 336 }
321 } 337 }
322 338
@@ -384,7 +400,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
384 warp_Texture texture; 400 warp_Texture texture;
385 using ( 401 using (
386 Bitmap image 402 Bitmap image
387 = TerrainSplat.Splat(terrain, textureIDs, startHeights, heightRanges, 403 = TerrainSplat.Splat(
404 terrain, textureIDs, startHeights, heightRanges,
388 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain)) 405 new Vector3d(globalX, globalY, 0.0), m_scene.AssetService, textureTerrain))
389 { 406 {
390 texture = new warp_Texture(image); 407 texture = new warp_Texture(image);
@@ -660,7 +677,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
660 #endregion Rendering Methods 677 #endregion Rendering Methods
661 678
662 #region Static Helpers 679 #region Static Helpers
663
664 // Note: axis change. 680 // Note: axis change.
665 private static warp_Vector ConvertVector(float x, float y, float z) 681 private static warp_Vector ConvertVector(float x, float y, float z)
666 { 682 {
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index d862f18..7370156 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -141,25 +141,23 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
141 141
142 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 142 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
143 { 143 {
144 List<MapBlockData> blocks = new List<MapBlockData>(); 144 Util.FireAndForget(x =>
145 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
146 { 145 {
147 // final block, closing the search result 146 List<MapBlockData> blocks = new List<MapBlockData>();
148 AddFinalBlock(blocks); 147 if (mapName.Length < 3 || (mapName.EndsWith("#") && mapName.Length < 4))
148 {
149 // final block, closing the search result
150 AddFinalBlock(blocks,mapName);
149 151
150 // flags are agent flags sent from the viewer. 152 // flags are agent flags sent from the viewer.
151 // they have different values depending on different viewers, apparently 153 // they have different values depending on different viewers, apparently
152 remoteClient.SendMapBlock(blocks, flags); 154 remoteClient.SendMapBlock(blocks, flags);
153 remoteClient.SendAlertMessage("Use a search string with at least 3 characters"); 155 remoteClient.SendAlertMessage("Use a search string with at least 3 characters");
154 return; 156 return;
155 } 157 }
156 158
159 //m_log.DebugFormat("MAP NAME=({0})", mapName);
157 160
158 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
159
160 string mapNameOrig = mapName;
161 if (regionInfos.Count == 0)
162 {
163 // Hack to get around the fact that ll V3 now drops the port from the 161 // Hack to get around the fact that ll V3 now drops the port from the
164 // map name. See https://jira.secondlife.com/browse/VWR-28570 162 // map name. See https://jira.secondlife.com/browse/VWR-28570
165 // 163 //
@@ -168,69 +166,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
168 // or url encode if possible. 166 // or url encode if possible.
169 // the hacks we do with this viewer... 167 // the hacks we do with this viewer...
170 // 168 //
169 bool needOriginalName = false;
170 string mapNameOrig = mapName;
171 if (mapName.Contains("|")) 171 if (mapName.Contains("|"))
172 {
172 mapName = mapName.Replace('|', ':'); 173 mapName = mapName.Replace('|', ':');
174 needOriginalName = true;
175 }
173 if (mapName.Contains("+")) 176 if (mapName.Contains("+"))
177 {
174 mapName = mapName.Replace('+', ' '); 178 mapName = mapName.Replace('+', ' ');
179 needOriginalName = true;
180 }
175 if (mapName.Contains("!")) 181 if (mapName.Contains("!"))
182 {
176 mapName = mapName.Replace('!', '/'); 183 mapName = mapName.Replace('!', '/');
177 184 needOriginalName = true;
178 if (mapName != mapNameOrig) 185 }
179 regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); 186 if (mapName.Contains("."))
180 } 187 needOriginalName = true;
181 188
182 m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions. Flags={2}", mapName, regionInfos.Count, flags); 189 // try to fetch from GridServer
183 190 List<GridRegion> regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20);
184 if (regionInfos.Count > 0) 191 // if (regionInfos.Count == 0)
185 { 192 // remoteClient.SendAlertMessage("Hyperlink could not be established.");
186 foreach (GridRegion info in regionInfos) 193
194 //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count);
195
196 MapBlockData data;
197 if (regionInfos.Count > 0)
187 { 198 {
188 if ((flags & 2) == 2) // V2 sends this 199 foreach (GridRegion info in regionInfos)
189 { 200 {
190 List<MapBlockData> datas = WorldMap.Map2BlockFromGridRegion(info, flags); 201 data = new MapBlockData();
191 // ugh! V2-3 is very sensitive about the result being 202 data.Agents = 0;
192 // exactly the same as the requested name 203 data.Access = info.Access;
193 if (regionInfos.Count == 1 && (mapName != mapNameOrig)) 204 MapBlockData block = new MapBlockData();
194 datas.ForEach(d => d.Name = mapNameOrig); 205 WorldMap.MapBlockFromGridRegion(block, info, flags);
195 206
196 blocks.AddRange(datas); 207 if (flags == 2 && regionInfos.Count == 1 && needOriginalName)
197 } 208 block.Name = mapNameOrig;
198 else 209 blocks.Add(block);
199 {
200 MapBlockData data = WorldMap.MapBlockFromGridRegion(info, flags);
201 blocks.Add(data);
202 } 210 }
203 } 211 }
204 }
205 212
206 // final block, closing the search result 213 // final block, closing the search result
207 AddFinalBlock(blocks); 214 AddFinalBlock(blocks,mapNameOrig);
208 215
209 // flags are agent flags sent from the viewer. 216 // flags are agent flags sent from the viewer.
210 // they have different values depending on different viewers, apparently 217 // they have different values depending on different viewers, apparently
211 remoteClient.SendMapBlock(blocks, flags); 218 remoteClient.SendMapBlock(blocks, flags);
212 219
213 // send extra user messages for V3 220 // send extra user messages for V3
214 // because the UI is very confusing 221 // because the UI is very confusing
215 // while we don't fix the hard-coded urls 222 // while we don't fix the hard-coded urls
216 if (flags == 2) 223 if (flags == 2)
217 { 224 {
218 if (regionInfos.Count == 0) 225 if (regionInfos.Count == 0)
219 remoteClient.SendAlertMessage("No regions found with that name."); 226 remoteClient.SendAgentAlertMessage("No regions found with that name.", true);
220 // this seems unnecessary because found regions will show up in the search results 227// else if (regionInfos.Count == 1)
221 //else if (regionInfos.Count == 1) 228// remoteClient.SendAgentAlertMessage("Region found!", false);
222 // remoteClient.SendAlertMessage("Region found!"); 229 }
223 } 230 });
224 } 231 }
225 232
226 private void AddFinalBlock(List<MapBlockData> blocks) 233 private void AddFinalBlock(List<MapBlockData> blocks,string name)
227 { 234 {
228 // final block, closing the search result 235 // final block, closing the search result
229 MapBlockData data = new MapBlockData(); 236 MapBlockData data = new MapBlockData();
230 data.Agents = 0; 237 data.Agents = 0;
231 data.Access = (byte)SimAccess.NonExistent; 238 data.Access = (byte)SimAccess.NonExistent;
232 data.MapImageId = UUID.Zero; 239 data.MapImageId = UUID.Zero;
233 data.Name = ""; 240 data.Name = name;
234 data.RegionFlags = 0; 241 data.RegionFlags = 0;
235 data.WaterHeight = 0; // not used 242 data.WaterHeight = 0; // not used
236 data.X = 0; 243 data.X = 0;
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index db1187e..b8645e2 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -68,30 +68,33 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
68 private static readonly UUID STOP_UUID = UUID.Random(); 68 private static readonly UUID STOP_UUID = UUID.Random();
69 private static readonly string m_mapLayerPath = "0001/"; 69 private static readonly string m_mapLayerPath = "0001/";
70 70
71 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
72
73 private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
74 private Dictionary<UUID, Queue<MapBlockRequestData>> m_mapBlockRequests = new Dictionary<UUID, Queue<MapBlockRequestData>>();
75
71 private IMapImageGenerator m_mapImageGenerator; 76 private IMapImageGenerator m_mapImageGenerator;
72 private IMapImageUploadModule m_mapImageServiceModule; 77 private IMapImageUploadModule m_mapImageServiceModule;
73 78
74 private OpenSim.Framework.BlockingQueue<MapRequestState> requests = new OpenSim.Framework.BlockingQueue<MapRequestState>();
75
76 protected Scene m_scene; 79 protected Scene m_scene;
77 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>(); 80 private List<MapBlockData> cachedMapBlocks = new List<MapBlockData>();
78 private int cachedTime = 0;
79 private int blacklistTimeout = 10*60*1000; // 10 minutes
80 private byte[] myMapImageJPEG; 81 private byte[] myMapImageJPEG;
81 protected volatile bool m_Enabled = false; 82 protected volatile bool m_Enabled = false;
82 private Dictionary<UUID, MapRequestState> m_openRequests = new Dictionary<UUID, MapRequestState>(); 83 private ExpiringCache<string, int> m_blacklistedurls = new ExpiringCache<string, int>();
83 private Dictionary<string, int> m_blacklistedurls = new Dictionary<string, int>(); 84 private ExpiringCache<ulong, int> m_blacklistedregions = new ExpiringCache<ulong, int>();
84 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 85 private ExpiringCache<ulong, string> m_cachedRegionMapItemsAddress = new ExpiringCache<ulong, string>();
85 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 86 private ExpiringCache<ulong, OSDMap> m_cachedRegionMapItemsResponses =
87 new ExpiringCache<ulong, OSDMap>();
86 private List<UUID> m_rootAgents = new List<UUID>(); 88 private List<UUID> m_rootAgents = new List<UUID>();
87 private volatile bool threadrunning = false; 89 private volatile bool threadrunning = false;
88 90 // expire time for the blacklists in seconds
89 private IServiceThrottleModule m_ServiceThrottle; 91 private double expireBlackListTime = 600.0; // 10 minutes
90 92 // expire mapItems responses time in seconds. Throttles requests to regions that do answer
93 private const double expireResponsesTime = 120.0; // 2 minutes ?
91 //private int CacheRegionsDistance = 256; 94 //private int CacheRegionsDistance = 256;
92 95
93 #region INonSharedRegionModule Members 96 #region INonSharedRegionModule Members
94 public virtual void Initialise (IConfigSource config) 97 public virtual void Initialise(IConfigSource config)
95 { 98 {
96 string[] configSections = new string[] { "Map", "Startup" }; 99 string[] configSections = new string[] { "Map", "Startup" };
97 100
@@ -99,8 +102,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
99 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap") 102 config, "WorldMapModule", configSections, "WorldMap") == "WorldMap")
100 m_Enabled = true; 103 m_Enabled = true;
101 104
102 blacklistTimeout 105 expireBlackListTime = (double)Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60);
103 = Util.GetConfigVarFromSections<int>(config, "BlacklistTimeout", configSections, 10 * 60) * 1000;
104 } 106 }
105 107
106 public virtual void AddRegion(Scene scene) 108 public virtual void AddRegion(Scene scene)
@@ -128,7 +130,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
128 } 130 }
129 } 131 }
130 132
131 public virtual void RemoveRegion (Scene scene) 133 public virtual void RemoveRegion(Scene scene)
132 { 134 {
133 if (!m_Enabled) 135 if (!m_Enabled)
134 return; 136 return;
@@ -141,13 +143,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
141 } 143 }
142 } 144 }
143 145
144 public virtual void RegionLoaded (Scene scene) 146 public virtual void RegionLoaded(Scene scene)
145 { 147 {
146 if (!m_Enabled) 148 if (!m_Enabled)
147 return; 149 return;
148 150
149 m_ServiceThrottle = scene.RequestModuleInterface<IServiceThrottleModule>();
150
151 m_mapImageGenerator = m_scene.RequestModuleInterface<IMapImageGenerator>(); 151 m_mapImageGenerator = m_scene.RequestModuleInterface<IMapImageGenerator>();
152 m_mapImageServiceModule = m_scene.RequestModuleInterface<IMapImageUploadModule>(); 152 m_mapImageServiceModule = m_scene.RequestModuleInterface<IMapImageUploadModule>();
153 } 153 }
@@ -179,14 +179,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
179 179
180 MainServer.Instance.AddHTTPHandler(regionimage, 180 MainServer.Instance.AddHTTPHandler(regionimage,
181 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions() 181 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions()
182 { 182 {
183 AllowXForwardedFor = false, 183 AllowXForwardedFor = false,
184 ForgetTimeSpan = TimeSpan.FromMinutes(2), 184 ForgetTimeSpan = TimeSpan.FromMinutes(2),
185 MaxRequestsInTimeframe = 4, 185 MaxRequestsInTimeframe = 4,
186 ReportingName = "MAPDOSPROTECTOR", 186 ReportingName = "MAPDOSPROTECTOR",
187 RequestTimeSpan = TimeSpan.FromSeconds(10), 187 RequestTimeSpan = TimeSpan.FromSeconds(10),
188 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod 188 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
189 }).Process); 189 }).Process);
190 MainServer.Instance.AddLLSDHandler( 190 MainServer.Instance.AddLLSDHandler(
191 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 191 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
192 192
@@ -197,13 +197,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
197 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent; 197 m_scene.EventManager.OnMakeRootAgent += MakeRootAgent;
198 m_scene.EventManager.OnRegionUp += OnRegionUp; 198 m_scene.EventManager.OnRegionUp += OnRegionUp;
199 199
200// StartThread(new object()); 200 StartThread(new object());
201 } 201 }
202 202
203 // this has to be called with a lock on m_scene 203 // this has to be called with a lock on m_scene
204 protected virtual void RemoveHandlers() 204 protected virtual void RemoveHandlers()
205 { 205 {
206// StopThread(); 206 StopThread();
207 207
208 m_scene.EventManager.OnRegionUp -= OnRegionUp; 208 m_scene.EventManager.OnRegionUp -= OnRegionUp;
209 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent; 209 m_scene.EventManager.OnMakeRootAgent -= MakeRootAgent;
@@ -246,6 +246,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
246 public string MapLayerRequest(string request, string path, string param, 246 public string MapLayerRequest(string request, string path, string param,
247 UUID agentID, Caps caps) 247 UUID agentID, Caps caps)
248 { 248 {
249 // not sure about this....
250
249 //try 251 //try
250 // 252 //
251 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", 253 //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}",
@@ -261,54 +263,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
261 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is 263 // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is
262 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. 264 // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks.
263 265
264 if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) 266 //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048)
265 { 267 //{
266 ScenePresence avatarPresence = null; 268 // ScenePresence avatarPresence = null;
267 269
268 m_scene.TryGetScenePresence(agentID, out avatarPresence); 270 // m_scene.TryGetScenePresence(agentID, out avatarPresence);
269 271
270 if (avatarPresence != null) 272 // if (avatarPresence != null)
271 { 273 // {
272 bool lookup = false; 274 // bool lookup = false;
273 275
274 lock (cachedMapBlocks) 276 // lock (cachedMapBlocks)
275 { 277 // {
276 if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) 278 // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch()))
277 { 279 // {
278 List<MapBlockData> mapBlocks; 280 // List<MapBlockData> mapBlocks;
279 281
280 mapBlocks = cachedMapBlocks; 282 // mapBlocks = cachedMapBlocks;
281 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 283 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
282 } 284 // }
283 else 285 // else
284 { 286 // {
285 lookup = true; 287 // lookup = true;
286 } 288 // }
287 } 289 // }
288 if (lookup) 290 // if (lookup)
289 { 291 // {
290 List<MapBlockData> mapBlocks = new List<MapBlockData>(); ; 292 // List<MapBlockData> mapBlocks = new List<MapBlockData>(); ;
291 293
292 // Get regions that are within 8 regions of here 294 // List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
293 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 295 // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize,
294 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX - 8), 296 // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize,
295 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocX + 8), 297 // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize,
296 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY - 8), 298 // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize);
297 (int)Util.RegionToWorldLoc(m_scene.RegionInfo.RegionLocY + 8) ); 299 // foreach (GridRegion r in regions)
298 foreach (GridRegion r in regions) 300 // {
299 { 301 // MapBlockData block = new MapBlockData();
300 MapBlockData block = MapBlockFromGridRegion(r, 0); 302 // MapBlockFromGridRegion(block, r, 0);
301 mapBlocks.Add(block); 303 // mapBlocks.Add(block);
302 } 304 // }
303 avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); 305 // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0);
304 306
305 lock (cachedMapBlocks) 307 // lock (cachedMapBlocks)
306 cachedMapBlocks = mapBlocks; 308 // cachedMapBlocks = mapBlocks;
307 309
308 cachedTime = Util.UnixTimeSinceEpoch(); 310 // cachedTime = Util.UnixTimeSinceEpoch();
309 } 311 // }
310 } 312 // }
311 } 313 //}
312 314
313 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); 315 LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse();
314 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); 316 mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse());
@@ -334,9 +336,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
334 /// <returns></returns> 336 /// <returns></returns>
335 protected static OSDMapLayer GetOSDMapLayerResponse() 337 protected static OSDMapLayer GetOSDMapLayerResponse()
336 { 338 {
339 // not sure about this.... 2048 or master 5000 and hack above?
340
337 OSDMapLayer mapLayer = new OSDMapLayer(); 341 OSDMapLayer mapLayer = new OSDMapLayer();
338 mapLayer.Right = 5000; 342 mapLayer.Right = 2048;
339 mapLayer.Top = 5000; 343 mapLayer.Top = 2048;
340 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); 344 mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006");
341 345
342 return mapLayer; 346 return mapLayer;
@@ -365,6 +369,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
365 { 369 {
366 m_rootAgents.Remove(AgentId); 370 m_rootAgents.Remove(AgentId);
367 } 371 }
372 lock (m_mapBlockRequestEvent)
373 {
374 if (m_mapBlockRequests.ContainsKey(AgentId))
375 m_mapBlockRequests.Remove(AgentId);
376 }
368 } 377 }
369 #endregion 378 #endregion
370 379
@@ -379,14 +388,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
379 if (threadrunning) return; 388 if (threadrunning) return;
380 threadrunning = true; 389 threadrunning = true;
381 390
382// m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread"); 391 // m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread");
383 392
384 WorkManager.StartThread( 393 WorkManager.StartThread(
385 process, 394 process,
386 string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName), 395 string.Format("MapItemRequestThread ({0})", m_scene.RegionInfo.RegionName),
387 ThreadPriority.BelowNormal, 396 ThreadPriority.BelowNormal,
388 true, 397 true,
389 true); 398 false);
399 WorkManager.StartThread(
400 MapBlockSendThread,
401 string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName),
402 ThreadPriority.BelowNormal,
403 true,
404 false);
390 } 405 }
391 406
392 /// <summary> 407 /// <summary>
@@ -396,13 +411,29 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
396 { 411 {
397 MapRequestState st = new MapRequestState(); 412 MapRequestState st = new MapRequestState();
398 st.agentID = STOP_UUID; 413 st.agentID = STOP_UUID;
399 st.EstateID=0; 414 st.EstateID = 0;
400 st.flags=0; 415 st.flags = 0;
401 st.godlike=false; 416 st.godlike = false;
402 st.itemtype=0; 417 st.itemtype = 0;
403 st.regionhandle=0; 418 st.regionhandle = 0;
404 419
405 requests.Enqueue(st); 420 requests.Enqueue(st);
421
422 MapBlockRequestData req = new MapBlockRequestData();
423
424 req.client = null;
425 req.minX = 0;
426 req.maxX = 0;
427 req.minY = 0;
428 req.maxY = 0;
429 req.flags = 0;
430
431 lock (m_mapBlockRequestEvent)
432 {
433 m_mapBlockRequests[UUID.Zero] = new Queue<MapBlockRequestData>();
434 m_mapBlockRequests[UUID.Zero].Enqueue(req);
435 m_mapBlockRequestEvent.Set();
436 }
406 } 437 }
407 438
408 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, 439 public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
@@ -415,315 +446,372 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
415 if (!m_rootAgents.Contains(remoteClient.AgentId)) 446 if (!m_rootAgents.Contains(remoteClient.AgentId))
416 return; 447 return;
417 } 448 }
449
450 // local or remote request?
451 if (regionhandle != 0 && regionhandle != m_scene.RegionInfo.RegionHandle)
452 {
453 // its Remote Map Item Request
454 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes.
455 RequestMapItems("", remoteClient.AgentId, flags, EstateID, godlike, itemtype, regionhandle);
456 return;
457 }
458
418 uint xstart = 0; 459 uint xstart = 0;
419 uint ystart = 0; 460 uint ystart = 0;
420 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart); 461 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
421 if (itemtype == (int)GridItemType.AgentLocations) 462
463 // its about this region...
464
465 List<mapItemReply> mapitems = new List<mapItemReply>();
466 mapItemReply mapitem = new mapItemReply();
467
468 // viewers only ask for green dots to each region now
469 // except at login with regionhandle 0
470 // possible on some other rare ocasions
471 // use previus hack of sending all items with the green dots
472
473 bool adultRegion;
474 if (regionhandle == 0)
422 { 475 {
423 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 476 switch (itemtype)
424 { 477 {
425 // Just requesting map info about the current, local region 478 case (int)GridItemType.AgentLocations:
426 int tc = Environment.TickCount; 479 // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
427 List<mapItemReply> mapitems = new List<mapItemReply>(); 480
428 mapItemReply mapitem = new mapItemReply(); 481 int tc = Environment.TickCount;
429 if (m_scene.GetRootAgentCount() <= 1) 482 if (m_scene.GetRootAgentCount() <= 1)
430 { 483 {
431 mapitem = new mapItemReply( 484 mapitem = new mapItemReply(
432 xstart + 1, 485 xstart + 1,
433 ystart + 1, 486 ystart + 1,
434 UUID.Zero, 487 UUID.Zero,
435 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), 488 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
436 0, 0); 489 0, 0);
437 mapitems.Add(mapitem); 490 mapitems.Add(mapitem);
438 } 491 }
439 else 492 else
440 {
441 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
442 { 493 {
494 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
495 {
443 // Don't send a green dot for yourself 496 // Don't send a green dot for yourself
444 if (sp.UUID != remoteClient.AgentId) 497 if (sp.UUID != remoteClient.AgentId)
445 { 498 {
446 mapitem = new mapItemReply( 499 mapitem = new mapItemReply(
447 xstart + (uint)sp.AbsolutePosition.X, 500 xstart + (uint)sp.AbsolutePosition.X,
448 ystart + (uint)sp.AbsolutePosition.Y, 501 ystart + (uint)sp.AbsolutePosition.Y,
449 UUID.Zero, 502 UUID.Zero,
450 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()), 503 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
451 1, 0); 504 1, 0);
452 mapitems.Add(mapitem); 505 mapitems.Add(mapitem);
453 } 506 }
454 }); 507 });
455 } 508 }
456 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 509 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
457 } 510 break;
458 else
459 {
460 // Remote Map Item Request
461 511
462 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. 512 case (int)GridItemType.Telehub:
463 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 513 // Service 1 (MAP_ITEM_TELEHUB)
464 } 514
465 } 515 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
466 else if (itemtype == (int)GridItemType.LandForSale) // Service 7 (MAP_ITEM_LAND_FOR_SALE) 516 if (sog != null)
467 {
468 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
469 {
470 // Parcels
471 ILandChannel landChannel = m_scene.LandChannel;
472 List<ILandObject> parcels = landChannel.AllParcels();
473
474 // Local Map Item Request
475 List<mapItemReply> mapitems = new List<mapItemReply>();
476 mapItemReply mapitem = new mapItemReply();
477 if ((parcels != null) && (parcels.Count >= 1))
478 {
479 foreach (ILandObject parcel_interface in parcels)
480 { 517 {
481 // Play it safe 518 mapitem = new mapItemReply(
482 if (!(parcel_interface is LandObject)) 519 xstart + (uint)sog.AbsolutePosition.X,
483 continue; 520 ystart + (uint)sog.AbsolutePosition.Y,
521 UUID.Zero,
522 sog.Name,
523 0, // color (not used)
524 0 // 0 = telehub / 1 = infohub
525 );
526 mapitems.Add(mapitem);
527 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
528 }
529 break;
484 530
485 LandObject land = (LandObject)parcel_interface; 531 case (int)GridItemType.AdultLandForSale:
486 LandData parcel = land.LandData; 532 case (int)GridItemType.LandForSale:
487 533
488 // Show land for sale 534 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
489 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale) 535 adultRegion = m_scene.RegionInfo.RegionSettings.Maturity == 2;
490 { 536 if (adultRegion)
491 Vector3 min = parcel.AABBMin; 537 {
492 Vector3 max = parcel.AABBMax; 538 if (itemtype == (int)GridItemType.LandForSale)
493 float x = (min.X+max.X)/2; 539 break;
494 float y = (min.Y+max.Y)/2; 540 }
541 else
542 {
543 if (itemtype == (int)GridItemType.AdultLandForSale)
544 break;
545 }
495 546
496 mapitem = new mapItemReply( 547 // Parcels
548 ILandChannel landChannel = m_scene.LandChannel;
549 List<ILandObject> parcels = landChannel.AllParcels();
550
551 if ((parcels != null) && (parcels.Count >= 1))
552 {
553 foreach (ILandObject parcel_interface in parcels)
554 {
555 // Play it safe
556 if (!(parcel_interface is LandObject))
557 continue;
558
559 LandObject land = (LandObject)parcel_interface;
560 LandData parcel = land.LandData;
561
562 // Show land for sale
563 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale)
564 {
565 Vector3 min = parcel.AABBMin;
566 Vector3 max = parcel.AABBMax;
567 float x = (min.X + max.X) / 2;
568 float y = (min.Y + max.Y) / 2;
569 mapitem = new mapItemReply(
497 xstart + (uint)x, 570 xstart + (uint)x,
498 ystart + (uint)y, 571 ystart + (uint)y,
499 parcel.GlobalID, 572 parcel.GlobalID,
500 parcel.Name, 573 parcel.Name,
501 parcel.Area, 574 parcel.Area,
502 parcel.SalePrice 575 parcel.SalePrice
503 ); 576 );
504 mapitems.Add(mapitem); 577 mapitems.Add(mapitem);
578 }
505 } 579 }
506 } 580 }
507 } 581 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
508 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 582 break;
509 }
510 else
511 {
512 // Remote Map Item Request
513 583
514 // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. 584 case (uint)GridItemType.PgEvent:
515 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 585 case (uint)GridItemType.MatureEvent:
586 case (uint)GridItemType.AdultEvent:
587 case (uint)GridItemType.Classified:
588 case (uint)GridItemType.Popular:
589 // TODO
590 // just dont not cry about them
591 break;
592
593 default:
594 // unkown map item type
595 m_log.DebugFormat("[WORLD MAP]: Unknown MapItem type {1}", itemtype);
596 break;
516 } 597 }
517 } 598 }
518 else if (itemtype == (int)GridItemType.Telehub) // Service 1 (MAP_ITEM_TELEHUB) 599 else
519 { 600 {
520 if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) 601 // send all items till we get a better fix
521 {
522 List<mapItemReply> mapitems = new List<mapItemReply>();
523 mapItemReply mapitem = new mapItemReply();
524 602
525 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject); 603 // Service 6 right now (MAP_ITEM_AGENTS_LOCATION; green dots)
526 if (sog != null)
527 {
528 mapitem = new mapItemReply(
529 xstart + (uint)sog.AbsolutePosition.X,
530 ystart + (uint)sog.AbsolutePosition.Y,
531 UUID.Zero,
532 sog.Name,
533 0, // color (not used)
534 0 // 0 = telehub / 1 = infohub
535 );
536 mapitems.Add(mapitem);
537 604
538 remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); 605 int tc = Environment.TickCount;
539 } 606 if (m_scene.GetRootAgentCount() <= 1)
607 {
608 mapitem = new mapItemReply(
609 xstart + 1,
610 ystart + 1,
611 UUID.Zero,
612 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
613 0, 0);
614 mapitems.Add(mapitem);
540 } 615 }
541 else 616 else
542 { 617 {
543 // Remote Map Item Request 618 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
544 RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); 619 {
620 // Don't send a green dot for yourself
621 if (sp.UUID != remoteClient.AgentId)
622 {
623 mapitem = new mapItemReply(
624 xstart + (uint)sp.AbsolutePosition.X,
625 ystart + (uint)sp.AbsolutePosition.Y,
626 UUID.Zero,
627 Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString()),
628 1, 0);
629 mapitems.Add(mapitem);
630 }
631 });
545 } 632 }
546 } 633 remoteClient.SendMapItemReply(mapitems.ToArray(), 6, flags);
547 } 634 mapitems.Clear();
548 635
549 private int nAsyncRequests = 0; 636 // Service 1 (MAP_ITEM_TELEHUB)
550 /// <summary> 637
551 /// Processing thread main() loop for doing remote mapitem requests 638 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
552 /// </summary> 639 if (sog != null)
553 public void process()
554 {
555 //const int MAX_ASYNC_REQUESTS = 20;
556 try
557 {
558 while (true)
559 { 640 {
560 MapRequestState st = requests.Dequeue(1000); 641 mapitem = new mapItemReply(
642 xstart + (uint)sog.AbsolutePosition.X,
643 ystart + (uint)sog.AbsolutePosition.Y,
644 UUID.Zero,
645 sog.Name,
646 0, // color (not used)
647 0 // 0 = telehub / 1 = infohub
648 );
649 mapitems.Add(mapitem);
650 remoteClient.SendMapItemReply(mapitems.ToArray(), 1, flags);
651 mapitems.Clear();
652 }
561 653
562 // end gracefully 654 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
563 if (st.agentID == STOP_UUID)
564 break;
565 655
566 if (st.agentID != UUID.Zero) 656 uint its = 7;
657 if (m_scene.RegionInfo.RegionSettings.Maturity == 2)
658 its = 10;
659
660 // Parcels
661 ILandChannel landChannel = m_scene.LandChannel;
662 List<ILandObject> parcels = landChannel.AllParcels();
663
664 if ((parcels != null) && (parcels.Count >= 1))
665 {
666 foreach (ILandObject parcel_interface in parcels)
567 { 667 {
568 bool dorequest = true; 668 // Play it safe
569 lock (m_rootAgents) 669 if (!(parcel_interface is LandObject))
570 { 670 continue;
571 if (!m_rootAgents.Contains(st.agentID)) 671
572 dorequest = false; 672 LandObject land = (LandObject)parcel_interface;
573 } 673 LandData parcel = land.LandData;
574 674
575 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 675 // Show land for sale
676 if ((parcel.Flags & (uint)ParcelFlags.ForSale) == (uint)ParcelFlags.ForSale)
576 { 677 {
577 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break 678 Vector3 min = parcel.AABBMin;
578 Thread.Sleep(80); 679 Vector3 max = parcel.AABBMax;
579 680 float x = (min.X + max.X) / 2;
580 RequestMapItemsDelegate d = RequestMapItemsAsync; 681 float y = (min.Y + max.Y) / 2;
581 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null); 682 mapitem = new mapItemReply(
582 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); 683 xstart + (uint)x,
583 //RequestMapItemsCompleted(response); 684 ystart + (uint)y,
584 Interlocked.Increment(ref nAsyncRequests); 685 parcel.GlobalID,
686 parcel.Name,
687 parcel.Area,
688 parcel.SalePrice
689 );
690 mapitems.Add(mapitem);
585 } 691 }
586 } 692 }
587 693 if(mapitems.Count >0)
588 Watchdog.UpdateThread(); 694 remoteClient.SendMapItemReply(mapitems.ToArray(), its, flags);
695 mapitems.Clear();
589 } 696 }
590 } 697 }
591 catch (Exception e)
592 {
593 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
594 }
595
596 threadrunning = false;
597 Watchdog.RemoveThread();
598 } 698 }
599 699
600 const int MAX_ASYNC_REQUESTS = 20; 700 private int nAsyncRequests = 0;
601
602 /// <summary> 701 /// <summary>
603 /// Enqueues the map item request into the services throttle processing thread 702 /// Processing thread main() loop for doing remote mapitem requests
604 /// </summary> 703 /// </summary>
605 /// <param name="state"></param> 704 public void process()
606 public void EnqueueMapItemRequest(MapRequestState st)
607 { 705 {
706 const int MAX_ASYNC_REQUESTS = 20;
707 ScenePresence av = null;
708 MapRequestState st = null;
608 709
609 m_ServiceThrottle.Enqueue("map-item", st.regionhandle.ToString() + st.agentID.ToString(), delegate 710 try
610 { 711 {
611 if (st.agentID != UUID.Zero) 712 while (true)
612 { 713 {
613 bool dorequest = true; 714 Watchdog.UpdateThread();
614 lock (m_rootAgents)
615 {
616 if (!m_rootAgents.Contains(st.agentID))
617 dorequest = false;
618 }
619 715
620 if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) 716 av = null;
621 { 717 st = null;
622 if (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
623 {
624 // AH!!! Recursive !
625 // Put this request back in the queue and return
626 EnqueueMapItemRequest(st);
627 return;
628 }
629 718
630 RequestMapItemsDelegate d = RequestMapItemsAsync; 719 st = requests.Dequeue(4900); // timeout to make watchdog happy
631 d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null);
632 //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
633 //RequestMapItemsCompleted(response);
634 Interlocked.Increment(ref nAsyncRequests);
635 }
636 }
637 });
638 }
639 720
640 /// <summary> 721 if (st == null || st.agentID == UUID.Zero)
641 /// Sends the mapitem response to the IClientAPI 722 continue;
642 /// </summary>
643 /// <param name="response">The OSDMap Response for the mapitem</param>
644 private void RequestMapItemsCompleted(IAsyncResult iar)
645 {
646 AsyncResult result = (AsyncResult)iar;
647 RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate;
648 723
649 OSDMap response = (OSDMap)icon.EndInvoke(iar); 724 // end gracefully
725 if (st.agentID == STOP_UUID)
726 break;
650 727
651 Interlocked.Decrement(ref nAsyncRequests); 728 // agent gone?
729
730 m_scene.TryGetScenePresence(st.agentID, out av);
731 if (av == null || av.IsChildAgent || av.IsDeleted || av.IsInTransit)
732 continue;
652 733
653 if (!response.ContainsKey("requestID")) 734 // region unreachable?
654 return; 735 if (m_blacklistedregions.Contains(st.regionhandle))
736 continue;
655 737
656 UUID requestID = response["requestID"].AsUUID(); 738 bool dorequest = true;
739 OSDMap responseMap = null;
657 740
658 if (requestID != UUID.Zero) 741 // check if we are already serving this region
659 { 742 lock (m_cachedRegionMapItemsResponses)
660 MapRequestState mrs = new MapRequestState();
661 mrs.agentID = UUID.Zero;
662 lock (m_openRequests)
663 {
664 if (m_openRequests.ContainsKey(requestID))
665 { 743 {
666 mrs = m_openRequests[requestID]; 744 if (m_cachedRegionMapItemsResponses.Contains(st.regionhandle))
667 m_openRequests.Remove(requestID); 745 {
746 m_cachedRegionMapItemsResponses.TryGetValue(st.regionhandle, out responseMap);
747 dorequest = false;
748 }
749 else
750 m_cachedRegionMapItemsResponses.Add(st.regionhandle, null, expireResponsesTime); // a bit more time for the access
668 } 751 }
669 }
670 752
671 if (mrs.agentID != UUID.Zero) 753 if (dorequest)
672 {
673 ScenePresence av = null;
674 m_scene.TryGetScenePresence(mrs.agentID, out av);
675 if (av != null)
676 { 754 {
677 if (response.ContainsKey(mrs.itemtype.ToString())) 755 // nothig for region, fire a request
756 Interlocked.Increment(ref nAsyncRequests);
757 MapRequestState rst = st;
758 Util.FireAndForget(x =>
678 { 759 {
679 List<mapItemReply> returnitems = new List<mapItemReply>(); 760 RequestMapItemsAsync(rst.agentID, rst.flags, rst.EstateID, rst.godlike, rst.itemtype, rst.regionhandle);
680 OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()]; 761 });
681 for (int i = 0; i < itemarray.Count; i++) 762 }
682 { 763 else
683 OSDMap mapitem = (OSDMap)itemarray[i]; 764 {
684 mapItemReply mi = new mapItemReply(); 765 // do we have the response?
685 mi.FromOSD(mapitem); 766 if (responseMap != null)
686 returnitems.Add(mi);
687 }
688 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags);
689 }
690
691 // Service 7 (MAP_ITEM_LAND_FOR_SALE)
692 uint itemtype = (uint)GridItemType.LandForSale;
693
694 if (response.ContainsKey(itemtype.ToString()))
695 { 767 {
696 List<mapItemReply> returnitems = new List<mapItemReply>(); 768 if(av!=null)
697 OSDArray itemarray = (OSDArray)response[itemtype.ToString()];
698 for (int i = 0; i < itemarray.Count; i++)
699 { 769 {
700 OSDMap mapitem = (OSDMap)itemarray[i]; 770 // this will mainly only send green dots now
701 mapItemReply mi = new mapItemReply(); 771 if (responseMap.ContainsKey(st.itemtype.ToString()))
702 mi.FromOSD(mapitem); 772 {
703 returnitems.Add(mi); 773 List<mapItemReply> returnitems = new List<mapItemReply>();
774 OSDArray itemarray = (OSDArray)responseMap[st.itemtype.ToString()];
775 for (int i = 0; i < itemarray.Count; i++)
776 {
777 OSDMap mapitem = (OSDMap)itemarray[i];
778 mapItemReply mi = new mapItemReply();
779 mi.x = (uint)mapitem["X"].AsInteger();
780 mi.y = (uint)mapitem["Y"].AsInteger();
781 mi.id = mapitem["ID"].AsUUID();
782 mi.Extra = mapitem["Extra"].AsInteger();
783 mi.Extra2 = mapitem["Extra2"].AsInteger();
784 mi.name = mapitem["Name"].AsString();
785 returnitems.Add(mi);
786 }
787 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), st.itemtype, st.flags & 0xffff);
788 }
704 } 789 }
705 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
706 } 790 }
707 791 else
708 // Service 1 (MAP_ITEM_TELEHUB)
709 itemtype = (uint)GridItemType.Telehub;
710
711 if (response.ContainsKey(itemtype.ToString()))
712 { 792 {
713 List<mapItemReply> returnitems = new List<mapItemReply>(); 793 // request still beeing processed, enqueue it back
714 OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; 794 requests.Enqueue(st);
715 for (int i = 0; i < itemarray.Count; i++) 795 if (requests.Count() < 3)
716 { 796 Thread.Sleep(100);
717 OSDMap mapitem = (OSDMap)itemarray[i];
718 mapItemReply mi = new mapItemReply();
719 mi.FromOSD(mapitem);
720 returnitems.Add(mi);
721 }
722 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags);
723 } 797 }
724 } 798 }
799
800 while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break
801 {
802 Thread.Sleep(100);
803 Watchdog.UpdateThread();
804 }
725 } 805 }
726 } 806 }
807
808 catch (Exception e)
809 {
810 m_log.ErrorFormat("[WORLD MAP]: Map item request thread terminated abnormally with exception {0}", e);
811 }
812
813 threadrunning = false;
814 Watchdog.RemoveThread();
727 } 815 }
728 816
729 /// <summary> 817 /// <summary>
@@ -746,11 +834,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
746 st.godlike = godlike; 834 st.godlike = godlike;
747 st.itemtype = itemtype; 835 st.itemtype = itemtype;
748 st.regionhandle = regionhandle; 836 st.regionhandle = regionhandle;
749 EnqueueMapItemRequest(st); 837
838 requests.Enqueue(st);
750 } 839 }
751 840
752 private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags, 841 uint[] itemTypesForcedSend = new uint[] { 6, 1, 7, 10 }; // green dots, infohub, land sells
753 uint EstateID, bool godlike, uint itemtype, ulong regionhandle); 842
754 /// <summary> 843 /// <summary>
755 /// Does the actual remote mapitem request 844 /// Does the actual remote mapitem request
756 /// This should be called from an asynchronous thread 845 /// This should be called from an asynchronous thread
@@ -765,94 +854,55 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
765 /// <param name="itemtype">passed in from packet</param> 854 /// <param name="itemtype">passed in from packet</param>
766 /// <param name="regionhandle">Region we're looking up</param> 855 /// <param name="regionhandle">Region we're looking up</param>
767 /// <returns></returns> 856 /// <returns></returns>
768 private OSDMap RequestMapItemsAsync(UUID id, uint flags, 857 private void RequestMapItemsAsync(UUID id, uint flags,
769 uint EstateID, bool godlike, uint itemtype, ulong regionhandle) 858 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
770 { 859 {
771// m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); 860 // m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype);
772 861
773 string httpserver = ""; 862 string httpserver = "";
774 bool blacklisted = false; 863 bool blacklisted = false;
775 lock (m_blacklistedregions)
776 {
777 if (m_blacklistedregions.ContainsKey(regionhandle))
778 {
779 if (Environment.TickCount > (m_blacklistedregions[regionhandle] + blacklistTimeout))
780 {
781 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted region {0}", regionhandle);
782 864
783 m_blacklistedregions.Remove(regionhandle); 865 lock (m_blacklistedregions)
784 } 866 blacklisted = m_blacklistedregions.Contains(regionhandle);
785 else
786 blacklisted = true;
787 }
788 }
789 867
790 if (blacklisted) 868 if (blacklisted)
791 return new OSDMap(); 869 {
870 Interlocked.Decrement(ref nAsyncRequests);
871 return;
872 }
792 873
793 UUID requestID = UUID.Random(); 874 UUID requestID = UUID.Random();
794 lock (m_cachedRegionMapItemsAddress) 875 lock (m_cachedRegionMapItemsAddress)
795 { 876 m_cachedRegionMapItemsAddress.TryGetValue(regionhandle, out httpserver);
796 if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 877
797 httpserver = m_cachedRegionMapItemsAddress[regionhandle]; 878 if (httpserver == null || httpserver.Length == 0)
798 }
799 if (httpserver.Length == 0)
800 { 879 {
801 uint x = 0, y = 0; 880 uint x = 0, y = 0;
802 Util.RegionHandleToWorldLoc(regionhandle, out x, out y); 881 Util.RegionHandleToWorldLoc(regionhandle, out x, out y);
882
803 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 883 GridRegion mreg = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
804 884
805 if (mreg != null) 885 if (mreg != null)
806 { 886 {
807 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString(); 887 httpserver = mreg.ServerURI + "MAP/MapItems/" + regionhandle.ToString();
808 lock (m_cachedRegionMapItemsAddress) 888 lock (m_cachedRegionMapItemsAddress)
809 { 889 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle, httpserver, 2.0 * expireBlackListTime);
810 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle))
811 m_cachedRegionMapItemsAddress.Add(regionhandle, httpserver);
812 }
813 }
814 else
815 {
816 lock (m_blacklistedregions)
817 {
818 if (!m_blacklistedregions.ContainsKey(regionhandle))
819 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
820 }
821 //m_log.InfoFormat("[WORLD MAP]: Blacklisted region {0}", regionhandle.ToString());
822 } 890 }
823 } 891 }
824 892
825 blacklisted = false;
826 lock (m_blacklistedurls) 893 lock (m_blacklistedurls)
827 { 894 {
828 if (m_blacklistedurls.ContainsKey(httpserver)) 895 if (httpserver == null || httpserver.Length == 0 || m_blacklistedurls.Contains(httpserver))
829 { 896 {
830 if (Environment.TickCount > (m_blacklistedurls[httpserver] + blacklistTimeout)) 897 // Can't find the http server or its blocked
831 { 898 lock (m_blacklistedregions)
832 m_log.DebugFormat("[WORLD MAP]: Unblock blacklisted URL {0}", httpserver); 899 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
833 900
834 m_blacklistedurls.Remove(httpserver); 901 Interlocked.Decrement(ref nAsyncRequests);
835 } 902 return;
836 else
837 blacklisted = true;
838 } 903 }
839 } 904 }
840 905
841 // Can't find the http server
842 if (httpserver.Length == 0 || blacklisted)
843 return new OSDMap();
844
845 MapRequestState mrs = new MapRequestState();
846 mrs.agentID = id;
847 mrs.EstateID = EstateID;
848 mrs.flags = flags;
849 mrs.godlike = godlike;
850 mrs.itemtype=itemtype;
851 mrs.regionhandle = regionhandle;
852
853 lock (m_openRequests)
854 m_openRequests.Add(requestID, mrs);
855
856 WebRequest mapitemsrequest = null; 906 WebRequest mapitemsrequest = null;
857 try 907 try
858 { 908 {
@@ -861,132 +911,144 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
861 catch (Exception e) 911 catch (Exception e)
862 { 912 {
863 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); 913 m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e);
864 return new OSDMap(); 914 Interlocked.Decrement(ref nAsyncRequests);
915 return;
865 } 916 }
866 917
867 mapitemsrequest.Method = "POST"; 918 mapitemsrequest.Method = "POST";
868 mapitemsrequest.ContentType = "application/xml+llsd"; 919 mapitemsrequest.ContentType = "application/xml+llsd";
869 OSDMap RAMap = new OSDMap();
870 920
921 OSDMap RAMap = new OSDMap();
871 // string RAMapString = RAMap.ToString(); 922 // string RAMapString = RAMap.ToString();
872 OSD LLSDofRAMap = RAMap; // RENAME if this works 923 OSD LLSDofRAMap = RAMap; // RENAME if this works
873 924
874 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap); 925 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
926
875 OSDMap responseMap = new OSDMap(); 927 OSDMap responseMap = new OSDMap();
876 responseMap["requestID"] = OSD.FromUUID(requestID);
877 928
878 Stream os = null;
879 try 929 try
880 { // send the Post 930 { // send the Post
881 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send 931 mapitemsrequest.ContentLength = buffer.Length; //Count bytes to send
882 os = mapitemsrequest.GetRequestStream(); 932 using (Stream os = mapitemsrequest.GetRequestStream())
883 os.Write(buffer, 0, buffer.Length); //Send it 933 os.Write(buffer, 0, buffer.Length); //Send it
884 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver); 934 //m_log.DebugFormat("[WORLD MAP]: Getting MapItems from {0}", httpserver);
885 } 935 }
886 catch (WebException ex) 936 catch (WebException ex)
887 { 937 {
888 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); 938 m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message);
889 responseMap["connect"] = OSD.FromBoolean(false); 939 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
890 lock (m_blacklistedurls) 940 lock (m_blacklistedurls)
891 { 941 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
892 if (!m_blacklistedurls.ContainsKey(httpserver)) 942 lock (m_blacklistedregions)
893 m_blacklistedurls.Add(httpserver, Environment.TickCount); 943 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
894 }
895
896 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver);
897 944
898 return responseMap; 945 Interlocked.Decrement(ref nAsyncRequests);
946 return;
899 } 947 }
900 catch 948 catch
901 { 949 {
902 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 950 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
903 responseMap["connect"] = OSD.FromBoolean(false); 951 Interlocked.Decrement(ref nAsyncRequests);
904 return responseMap; 952 return;
905 }
906 finally
907 {
908 if (os != null)
909 os.Dispose();
910 } 953 }
911 954
912 string response_mapItems_reply = null; 955 string response_mapItems_reply = null;
913 { 956 { // get the response
914 try 957 try
915 { 958 {
916 using (WebResponse webResponse = mapitemsrequest.GetResponse()) 959 using (WebResponse webResponse = mapitemsrequest.GetResponse())
917 { 960 {
918 if (webResponse != null) 961 if (webResponse != null)
919 { 962 {
920 using (Stream s = webResponse.GetResponseStream()) 963 using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
921 using (StreamReader sr = new StreamReader(s)) 964 {
922 response_mapItems_reply = sr.ReadToEnd().Trim(); 965 response_mapItems_reply = sr.ReadToEnd().Trim();
966 }
923 } 967 }
924 else 968 else
925 { 969 {
926 return new OSDMap(); 970 Interlocked.Decrement(ref nAsyncRequests);
927 } 971 return;
928 } 972 }
973 }
929 } 974 }
930 catch (WebException) 975 catch (WebException)
931 { 976 {
932 responseMap["connect"] = OSD.FromBoolean(false);
933 lock (m_blacklistedurls) 977 lock (m_blacklistedurls)
934 { 978 m_blacklistedurls.AddOrUpdate(httpserver, 0, expireBlackListTime);
935 if (!m_blacklistedurls.ContainsKey(httpserver)) 979 lock (m_blacklistedregions)
936 m_blacklistedurls.Add(httpserver, Environment.TickCount); 980 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
937 }
938 981
939 m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); 982 m_log.WarnFormat("[WORLD MAP]: Blacklisted url {0}", httpserver);
940 983
941 return responseMap; 984 Interlocked.Decrement(ref nAsyncRequests);
985 return;
942 } 986 }
943 catch 987 catch
944 { 988 {
945 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); 989 m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver);
946 responseMap["connect"] = OSD.FromBoolean(false);
947 lock (m_blacklistedregions) 990 lock (m_blacklistedregions)
948 { 991 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
949 if (!m_blacklistedregions.ContainsKey(regionhandle))
950 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
951 }
952 992
953 return responseMap; 993 Interlocked.Decrement(ref nAsyncRequests);
994 return;
954 } 995 }
955 996
956 OSD rezResponse = null;
957 try 997 try
958 { 998 {
959 rezResponse = OSDParser.DeserializeLLSDXml(response_mapItems_reply); 999 responseMap = (OSDMap)OSDParser.DeserializeLLSDXml(response_mapItems_reply);
960
961 responseMap = (OSDMap)rezResponse;
962 responseMap["requestID"] = OSD.FromUUID(requestID);
963 } 1000 }
964 catch (Exception ex) 1001 catch (Exception ex)
965 { 1002 {
966 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); 1003 m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message);
967 responseMap["connect"] = OSD.FromBoolean(false);
968
969 lock (m_blacklistedregions) 1004 lock (m_blacklistedregions)
970 { 1005 m_blacklistedregions.AddOrUpdate(regionhandle, 0, expireBlackListTime);
971 if (!m_blacklistedregions.ContainsKey(regionhandle))
972 m_blacklistedregions.Add(regionhandle, Environment.TickCount);
973 }
974 1006
975 return responseMap; 1007 Interlocked.Decrement(ref nAsyncRequests);
1008 return;
976 } 1009 }
977 } 1010 }
978 1011
979 if (!responseMap.ContainsKey(itemtype.ToString())) // remote sim doesnt have the stated region handle 1012 // cache the response that may include other valid items
1013 lock (m_cachedRegionMapItemsResponses)
1014 m_cachedRegionMapItemsResponses.AddOrUpdate(regionhandle, responseMap, expireResponsesTime);
1015
1016 flags &= 0xffff;
1017
1018 if (id != UUID.Zero)
980 { 1019 {
981 m_log.DebugFormat("[WORLD MAP]: Remote sim does not have the stated region. Blacklisting."); 1020 ScenePresence av = null;
982 lock (m_blacklistedregions) 1021 m_scene.TryGetScenePresence(id, out av);
1022 if (av != null && !av.IsChildAgent && !av.IsDeleted && !av.IsInTransit)
983 { 1023 {
984 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1024 // send all the items or viewers will never ask for them, except green dots
985 m_blacklistedregions.Add(regionhandle, Environment.TickCount); 1025 foreach (uint itfs in itemTypesForcedSend)
1026 {
1027 if (responseMap.ContainsKey(itfs.ToString()))
1028 {
1029 List<mapItemReply> returnitems = new List<mapItemReply>();
1030// OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()];
1031 OSDArray itemarray = (OSDArray)responseMap[itfs.ToString()];
1032 for (int i = 0; i < itemarray.Count; i++)
1033 {
1034 OSDMap mapitem = (OSDMap)itemarray[i];
1035 mapItemReply mi = new mapItemReply();
1036 mi.x = (uint)mapitem["X"].AsInteger();
1037 mi.y = (uint)mapitem["Y"].AsInteger();
1038 mi.id = mapitem["ID"].AsUUID();
1039 mi.Extra = mapitem["Extra"].AsInteger();
1040 mi.Extra2 = mapitem["Extra2"].AsInteger();
1041 mi.name = mapitem["Name"].AsString();
1042 returnitems.Add(mi);
1043 }
1044// av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags);
1045 av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itfs, flags);
1046 }
1047 }
986 } 1048 }
987 } 1049 }
988 1050
989 return responseMap; 1051 Interlocked.Decrement(ref nAsyncRequests);
990 } 1052 }
991 1053
992 /// <summary> 1054 /// <summary>
@@ -996,87 +1058,133 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
996 /// <param name="minY"></param> 1058 /// <param name="minY"></param>
997 /// <param name="maxX"></param> 1059 /// <param name="maxX"></param>
998 /// <param name="maxY"></param> 1060 /// <param name="maxY"></param>
999 public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1061 public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1062 {
1063 m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
1064
1065 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
1066 }
1067
1068 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1069 {
1070 MapBlockRequestData req = new MapBlockRequestData();
1071
1072 req.client = remoteClient;
1073 req.minX = minX;
1074 req.maxX = maxX;
1075 req.minY = minY;
1076 req.maxY = maxY;
1077 req.flags = flag;
1078
1079 lock (m_mapBlockRequestEvent)
1080 {
1081 if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId))
1082 m_mapBlockRequests[remoteClient.AgentId] = new Queue<MapBlockRequestData>();
1083 m_mapBlockRequests[remoteClient.AgentId].Enqueue(req);
1084 m_mapBlockRequestEvent.Set();
1085 }
1086
1087 return new List<MapBlockData>();
1088 }
1089
1090 protected void MapBlockSendThread()
1000 { 1091 {
1001 if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible 1092 while (true)
1002 { 1093 {
1003 List<MapBlockData> response = new List<MapBlockData>(); 1094 List<MapBlockRequestData> thisRunData = new List<MapBlockRequestData>();
1004 1095
1005 // this should return one mapblock at most. It is triggered by a click 1096 m_mapBlockRequestEvent.WaitOne();
1006 // on an unloaded square. 1097 lock (m_mapBlockRequestEvent)
1007 // But make sure: Look whether the one we requested is in there
1008 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1009 (int)Util.RegionToWorldLoc((uint)minX), (int)Util.RegionToWorldLoc((uint)maxX),
1010 (int)Util.RegionToWorldLoc((uint)minY), (int)Util.RegionToWorldLoc((uint)maxY) );
1011
1012 m_log.DebugFormat("[WORLD MAP MODULE] RequestMapBlocks min=<{0},{1}>, max=<{2},{3}>, flag={4}, cntFound={5}",
1013 minX, minY, maxX, maxY, flag.ToString("X"), regions.Count);
1014 if (regions != null)
1015 { 1098 {
1016 foreach (GridRegion r in regions) 1099 int total = 0;
1100 foreach (Queue<MapBlockRequestData> q in m_mapBlockRequests.Values)
1017 { 1101 {
1018 if (r.RegionLocX == Util.RegionToWorldLoc((uint)minX) 1102 if (q.Count > 0)
1019 && r.RegionLocY == Util.RegionToWorldLoc((uint)minY) ) 1103 thisRunData.Add(q.Dequeue());
1020 { 1104
1021 // found it => add it to response 1105 total += q.Count;
1022 // Version 2 viewers can handle the larger regions
1023 if ((flag & 2) == 2)
1024 response.AddRange(Map2BlockFromGridRegion(r, flag));
1025 else
1026 response.Add(MapBlockFromGridRegion(r, flag));
1027 break;
1028 }
1029 } 1106 }
1107
1108 if (total == 0)
1109 m_mapBlockRequestEvent.Reset();
1030 } 1110 }
1031 1111
1032 if (response.Count == 0) 1112 foreach (MapBlockRequestData req in thisRunData)
1033 { 1113 {
1034 // response still empty => couldn't find the map-tile the user clicked on => tell the client 1114 // Null client stops thread
1035 MapBlockData block = new MapBlockData(); 1115 if (req.client == null)
1036 block.X = (ushort)minX; 1116 return;
1037 block.Y = (ushort)minY; 1117
1038 block.Access = (byte)SimAccess.Down; // means 'simulator is offline' 1118 GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags);
1039 // block.Access = (byte)SimAccess.NonExistent;
1040 response.Add(block);
1041 } 1119 }
1042 // The lower 16 bits are an unsigned int16 1120
1043 remoteClient.SendMapBlock(response, flag & 0xffff); 1121 Thread.Sleep(50);
1044 }
1045 else
1046 {
1047 // normal mapblock request. Use the provided values
1048 GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag);
1049 } 1122 }
1050 } 1123 }
1051 1124
1052 protected virtual List<MapBlockData> GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) 1125 protected virtual List<MapBlockData> GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
1053 { 1126 {
1127 List<MapBlockData> allBlocks = new List<MapBlockData>();
1054 List<MapBlockData> mapBlocks = new List<MapBlockData>(); 1128 List<MapBlockData> mapBlocks = new List<MapBlockData>();
1055 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, 1129 List<GridRegion> regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID,
1056 (int)Util.RegionToWorldLoc((uint)(minX - 4)), (int)Util.RegionToWorldLoc((uint)(maxX + 4)), 1130 minX * (int)Constants.RegionSize,
1057 (int)Util.RegionToWorldLoc((uint)(minY - 4)), (int)Util.RegionToWorldLoc((uint)(maxY + 4)) ); 1131 maxX * (int)Constants.RegionSize,
1058 //m_log.DebugFormat("{0} GetAndSendBlocks. min=<{1},{2}>, max=<{3},{4}>, cntFound={5}", 1132 minY * (int)Constants.RegionSize,
1059 // LogHeader, minX, minY, maxX, maxY, regions.Count); 1133 maxY * (int)Constants.RegionSize);
1134
1135 // only send a negative answer for a single region request
1136 // corresponding to a click on the map. Current viewers
1137 // keep displaying "loading.." without this
1138 if (regions.Count == 0 && (flag & 0x10000) != 0 && minX == maxX && minY == maxY)
1139 {
1140 MapBlockData block = new MapBlockData();
1141 block.X = (ushort)minX;
1142 block.Y = (ushort)minY;
1143 block.MapImageId = UUID.Zero;
1144 block.Access = (byte)SimAccess.NonExistent;
1145 allBlocks.Add(block);
1146 mapBlocks.Add(block);
1147 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff);
1148 return allBlocks;
1149 }
1150
1151 flag &= 0xffff;
1152
1060 foreach (GridRegion r in regions) 1153 foreach (GridRegion r in regions)
1061 { 1154 {
1062 // Version 2 viewers can handle the larger regions 1155 if (r == null)
1063 if ((flag & 2) == 2) 1156 continue;
1064 mapBlocks.AddRange(Map2BlockFromGridRegion(r, flag)); 1157 MapBlockData block = new MapBlockData();
1065 else 1158 MapBlockFromGridRegion(block, r, flag);
1066 mapBlocks.Add(MapBlockFromGridRegion(r, flag)); 1159 mapBlocks.Add(block);
1160 allBlocks.Add(block);
1161
1162 if (mapBlocks.Count >= 10)
1163 {
1164 remoteClient.SendMapBlock(mapBlocks, flag);
1165 mapBlocks.Clear();
1166 Thread.Sleep(50);
1167 }
1067 } 1168 }
1068 remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); 1169 if (mapBlocks.Count > 0)
1170 remoteClient.SendMapBlock(mapBlocks, flag);
1069 1171
1070 return mapBlocks; 1172 return allBlocks;
1071 } 1173 }
1072 1174
1073 // Fill a passed MapBlockData from a GridRegion 1175 public void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag)
1074 public MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag)
1075 { 1176 {
1076 MapBlockData block = new MapBlockData(); 1177 if (r == null)
1178 {
1179 // we should not get here ??
1180// block.Access = (byte)SimAccess.Down; this is for a grid reply on r
1181 block.Access = (byte)SimAccess.NonExistent;
1182 block.MapImageId = UUID.Zero;
1183 return;
1184 }
1077 1185
1078 block.Access = r.Access; 1186 block.Access = r.Access;
1079 switch (flag & 0xffff) 1187 switch (flag)
1080 { 1188 {
1081 case 0: 1189 case 0:
1082 block.MapImageId = r.TerrainImage; 1190 block.MapImageId = r.TerrainImage;
@@ -1089,50 +1197,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1089 break; 1197 break;
1090 } 1198 }
1091 block.Name = r.RegionName; 1199 block.Name = r.RegionName;
1092 block.X = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocX); 1200 block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
1093 block.Y = (ushort)Util.WorldToRegionLoc((uint)r.RegionLocY); 1201 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1094 block.SizeX = (ushort) r.RegionSizeX; 1202 block.SizeX = (ushort)r.RegionSizeX;
1095 block.SizeY = (ushort) r.RegionSizeY; 1203 block.SizeY = (ushort)r.RegionSizeY;
1096 1204
1097 return block;
1098 } 1205 }
1099 1206
1100 public List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag)
1101 {
1102 List<MapBlockData> blocks = new List<MapBlockData>();
1103 MapBlockData block = new MapBlockData();
1104 if (r == null)
1105 {
1106 block.Access = (byte)SimAccess.Down;
1107 block.MapImageId = UUID.Zero;
1108 blocks.Add(block);
1109 }
1110 else
1111 {
1112 block.Access = r.Access;
1113 switch (flag & 0xffff)
1114 {
1115 case 0:
1116 block.MapImageId = r.TerrainImage;
1117 break;
1118 case 2:
1119 block.MapImageId = r.ParcelImage;
1120 break;
1121 default:
1122 block.MapImageId = UUID.Zero;
1123 break;
1124 }
1125 block.Name = r.RegionName;
1126 block.X = (ushort)(r.RegionLocX / Constants.RegionSize);
1127 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1128 block.SizeX = (ushort)r.RegionSizeX;
1129 block.SizeY = (ushort)r.RegionSizeY;
1130 blocks.Add(block);
1131 }
1132 return blocks;
1133 }
1134
1135
1136 public Hashtable OnHTTPThrottled(Hashtable keysvals) 1207 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1137 { 1208 {
1138 Hashtable reply = new Hashtable(); 1209 Hashtable reply = new Hashtable();
@@ -1145,67 +1216,71 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1145 1216
1146 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1217 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1147 { 1218 {
1148 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1149 Hashtable reply = new Hashtable(); 1219 Hashtable reply = new Hashtable();
1150 int statuscode = 200; 1220 int statuscode = 200;
1151 byte[] jpeg = new byte[0]; 1221 byte[] jpeg = new byte[0];
1152 1222
1153 if (myMapImageJPEG.Length == 0) 1223 if (m_scene.RegionInfo.RegionSettings.TerrainImageID != UUID.Zero)
1154 { 1224 {
1155 MemoryStream imgstream = null; 1225 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
1156 Bitmap mapTexture = new Bitmap(1,1);
1157 ManagedImage managedImage;
1158 Image image = (Image)mapTexture;
1159 1226
1160 try 1227 if (myMapImageJPEG.Length == 0)
1161 { 1228 {
1162 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data 1229 MemoryStream imgstream = null;
1230 Bitmap mapTexture = new Bitmap(1, 1);
1231 ManagedImage managedImage;
1232 Image image = (Image)mapTexture;
1233
1234 try
1235 {
1236 // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular jpeg data
1163 1237
1164 imgstream = new MemoryStream(); 1238 imgstream = new MemoryStream();
1165 1239
1166 // non-async because we know we have the asset immediately. 1240 // non-async because we know we have the asset immediately.
1167 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString()); 1241 AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString());
1168 1242
1169 // Decode image to System.Drawing.Image 1243 // Decode image to System.Drawing.Image
1170 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image)) 1244 if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image))
1171 { 1245 {
1172 // Save to bitmap 1246 // Save to bitmap
1173 mapTexture = new Bitmap(image); 1247 mapTexture = new Bitmap(image);
1174 1248
1175 EncoderParameters myEncoderParameters = new EncoderParameters(); 1249 EncoderParameters myEncoderParameters = new EncoderParameters();
1176 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L); 1250 myEncoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 95L);
1177 1251
1178 // Save bitmap to stream 1252 // Save bitmap to stream
1179 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters); 1253 mapTexture.Save(imgstream, GetEncoderInfo("image/jpeg"), myEncoderParameters);
1180 1254
1181 // Write the stream to a byte array for output 1255 // Write the stream to a byte array for output
1182 jpeg = imgstream.ToArray(); 1256 jpeg = imgstream.ToArray();
1183 myMapImageJPEG = jpeg; 1257 myMapImageJPEG = jpeg;
1258 }
1184 } 1259 }
1185 } 1260 catch (Exception)
1186 catch (Exception) 1261 {
1187 { 1262 // Dummy!
1188 // Dummy! 1263 m_log.Warn("[WORLD MAP]: Unable to generate Map image");
1189 m_log.Warn("[WORLD MAP]: Unable to generate Map image"); 1264 }
1190 } 1265 finally
1191 finally 1266 {
1192 { 1267 // Reclaim memory, these are unmanaged resources
1193 // Reclaim memory, these are unmanaged resources 1268 // If we encountered an exception, one or more of these will be null
1194 // If we encountered an exception, one or more of these will be null 1269 if (mapTexture != null)
1195 if (mapTexture != null) 1270 mapTexture.Dispose();
1196 mapTexture.Dispose();
1197 1271
1198 if (image != null) 1272 if (image != null)
1199 image.Dispose(); 1273 image.Dispose();
1200 1274
1201 if (imgstream != null) 1275 if (imgstream != null)
1202 imgstream.Dispose(); 1276 imgstream.Dispose();
1277 }
1278 }
1279 else
1280 {
1281 // Use cached version so we don't have to loose our mind
1282 jpeg = myMapImageJPEG;
1203 } 1283 }
1204 }
1205 else
1206 {
1207 // Use cached version so we don't have to loose our mind
1208 jpeg = myMapImageJPEG;
1209 } 1284 }
1210 1285
1211 reply["str_response_string"] = Convert.ToBase64String(jpeg); 1286 reply["str_response_string"] = Convert.ToBase64String(jpeg);
@@ -1267,22 +1342,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1267 1342
1268 foreach (GridRegion r in regions) 1343 foreach (GridRegion r in regions)
1269 { 1344 {
1270 MapBlockData mapBlock = MapBlockFromGridRegion(r, 0); 1345 MapBlockData mapBlock = new MapBlockData();
1346 MapBlockFromGridRegion(mapBlock, r, 0);
1271 AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString()); 1347 AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
1272 1348
1273 if (texAsset != null) 1349 if (texAsset != null)
1274 { 1350 {
1275 textures.Add(texAsset); 1351 textures.Add(texAsset);
1276 } 1352 }
1277 //else
1278 //{
1279 // // WHAT?!? This doesn't seem right. Commenting (diva)
1280 // texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString());
1281 // if (texAsset != null)
1282 // {
1283 // textures.Add(texAsset);
1284 // }
1285 //}
1286 } 1353 }
1287 1354
1288 foreach (AssetBase asset in textures) 1355 foreach (AssetBase asset in textures)
@@ -1320,17 +1387,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1320 if (consoleScene != null && consoleScene != m_scene) 1387 if (consoleScene != null && consoleScene != m_scene)
1321 return; 1388 return;
1322 1389
1323 if (m_mapImageGenerator == null) 1390 GenerateMaptile();
1324 {
1325 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1326 return;
1327 }
1328
1329 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
1330 {
1331 GenerateMaptile(mapbmp);
1332 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1333 }
1334 } 1391 }
1335 1392
1336 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) 1393 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
@@ -1338,9 +1395,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1338 uint xstart = 0; 1395 uint xstart = 0;
1339 uint ystart = 0; 1396 uint ystart = 0;
1340 1397
1341 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle,out xstart,out ystart); 1398 Util.RegionHandleToWorldLoc(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);
1342 // m_log.DebugFormat("{0} HandleRemoteMapItemRequest. loc=<{1},{2}>",
1343 // LogHeader, Util.WorldToRegionLoc(xstart), Util.WorldToRegionLoc(ystart));
1344 1399
1345 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots) 1400 // Service 6 (MAP_ITEM_AGENTS_LOCATION; green dots)
1346 1401
@@ -1362,8 +1417,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1362 } 1417 }
1363 else 1418 else
1364 { 1419 {
1365 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount()); 1420 OSDArray responsearr = new OSDArray(); // Don't preallocate. MT (m_scene.GetRootAgentCount());
1366 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 1421 m_scene.ForEachRootScenePresence(delegate (ScenePresence sp)
1367 { 1422 {
1368 OSDMap responsemapdata = new OSDMap(); 1423 OSDMap responsemapdata = new OSDMap();
1369 responsemapdata["X"] = OSD.FromInteger((int)(xstart + sp.AbsolutePosition.X)); 1424 responsemapdata["X"] = OSD.FromInteger((int)(xstart + sp.AbsolutePosition.X));
@@ -1377,28 +1432,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1377 responsemap["6"] = responsearr; 1432 responsemap["6"] = responsearr;
1378 } 1433 }
1379 1434
1380 // Service 7 (MAP_ITEM_LAND_FOR_SALE) 1435 // Service 7/10 (MAP_ITEM_LAND_FOR_SALE/ADULT)
1381 1436
1382 ILandChannel landChannel = m_scene.LandChannel; 1437 ILandChannel landChannel = m_scene.LandChannel;
1383 List<ILandObject> parcels = landChannel.AllParcels(); 1438 List<ILandObject> parcels = landChannel.AllParcels();
1384 1439
1385 if ((parcels == null) || (parcels.Count == 0)) 1440 if ((parcels != null) && (parcels.Count >= 0))
1386 { 1441 {
1387 OSDMap responsemapdata = new OSDMap(); 1442 OSDArray responsearr = new OSDArray(parcels.Count);
1388 responsemapdata["X"] = OSD.FromInteger((int)(xstart + 1));
1389 responsemapdata["Y"] = OSD.FromInteger((int)(ystart + 1));
1390 responsemapdata["ID"] = OSD.FromUUID(UUID.Zero);
1391 responsemapdata["Name"] = OSD.FromString("");
1392 responsemapdata["Extra"] = OSD.FromInteger(0);
1393 responsemapdata["Extra2"] = OSD.FromInteger(0);
1394 OSDArray responsearr = new OSDArray();
1395 responsearr.Add(responsemapdata);
1396
1397 responsemap["7"] = responsearr;
1398 }
1399 else
1400 {
1401 OSDArray responsearr = new OSDArray(m_scene.GetRootAgentCount());
1402 foreach (ILandObject parcel_interface in parcels) 1443 foreach (ILandObject parcel_interface in parcels)
1403 { 1444 {
1404 // Play it safe 1445 // Play it safe
@@ -1413,8 +1454,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1413 { 1454 {
1414 Vector3 min = parcel.AABBMin; 1455 Vector3 min = parcel.AABBMin;
1415 Vector3 max = parcel.AABBMax; 1456 Vector3 max = parcel.AABBMax;
1416 float x = (min.X+max.X)/2; 1457 float x = (min.X + max.X) / 2;
1417 float y = (min.Y+max.Y)/2; 1458 float y = (min.Y + max.Y) / 2;
1418 1459
1419 OSDMap responsemapdata = new OSDMap(); 1460 OSDMap responsemapdata = new OSDMap();
1420 responsemapdata["X"] = OSD.FromInteger((int)(xstart + x)); 1461 responsemapdata["X"] = OSD.FromInteger((int)(xstart + x));
@@ -1427,7 +1468,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1427 responsearr.Add(responsemapdata); 1468 responsearr.Add(responsemapdata);
1428 } 1469 }
1429 } 1470 }
1430 responsemap["7"] = responsearr; 1471
1472 if(responsearr.Count > 0)
1473 {
1474 if(m_scene.RegionInfo.RegionSettings.Maturity == 2)
1475 responsemap["10"] = responsearr;
1476 else
1477 responsemap["7"] = responsearr;
1478 }
1431 } 1479 }
1432 1480
1433 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero) 1481 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
@@ -1459,55 +1507,88 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1459 if (m_scene.Heightmap == null) 1507 if (m_scene.Heightmap == null)
1460 return; 1508 return;
1461 1509
1510 if (m_mapImageGenerator == null)
1511 {
1512 Console.WriteLine("No map image generator available for {0}", m_scene.Name);
1513 return;
1514 }
1462 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name); 1515 m_log.DebugFormat("[WORLD MAP]: Generating map image for {0}", m_scene.Name);
1463 1516
1464 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile()) 1517 using (Bitmap mapbmp = m_mapImageGenerator.CreateMapTile())
1465 { 1518 {
1466 // V1 (This Module)
1467 GenerateMaptile(mapbmp); 1519 GenerateMaptile(mapbmp);
1468 1520
1469 // v2/3 (MapImageServiceModule) 1521 if (m_mapImageServiceModule != null)
1470 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp); 1522 m_mapImageServiceModule.UploadMapTile(m_scene, mapbmp);
1471 } 1523 }
1472 } 1524 }
1473 1525
1474 private void GenerateMaptile(Bitmap mapbmp) 1526 private void GenerateMaptile(Bitmap mapbmp)
1475 { 1527 {
1476 byte[] data; 1528 bool needRegionSave = false;
1477 1529
1478 try 1530 // remove old assets
1531 UUID lastID = m_scene.RegionInfo.RegionSettings.TerrainImageID;
1532 if (lastID != UUID.Zero)
1479 { 1533 {
1480 data = OpenJPEG.EncodeFromImage(mapbmp, true); 1534 m_scene.AssetService.Delete(lastID.ToString());
1535 m_scene.RegionInfo.RegionSettings.TerrainImageID = UUID.Zero;
1536 needRegionSave = true;
1481 } 1537 }
1482 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke 1538
1539 lastID = m_scene.RegionInfo.RegionSettings.ParcelImageID;
1540 if (lastID != UUID.Zero)
1483 { 1541 {
1484 m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e); 1542 m_scene.AssetService.Delete(lastID.ToString());
1485 return; 1543 m_scene.RegionInfo.RegionSettings.ParcelImageID = UUID.Zero;
1544 needRegionSave = true;
1486 } 1545 }
1487 1546
1488 byte[] overlay = GenerateOverlay(); 1547 // bypass terrain image for large regions
1548 if (m_scene.RegionInfo.RegionSizeX <= Constants.RegionSize &&
1549 m_scene.RegionInfo.RegionSizeY <= Constants.RegionSize
1550 && mapbmp != null)
1551 {
1552 try
1553 {
1554 byte[] data;
1555
1556 data = OpenJPEG.EncodeFromImage(mapbmp, true);
1557
1558 if (data != null && data.Length > 0)
1559 {
1560 UUID terrainImageID = UUID.Random();
1489 1561
1490 UUID terrainImageID = UUID.Random(); 1562 AssetBase asset = new AssetBase(
1491 UUID parcelImageID = UUID.Zero; 1563 terrainImageID,
1564 "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(),
1565 (sbyte)AssetType.Texture,
1566 m_scene.RegionInfo.RegionID.ToString());
1567 asset.Data = data;
1568 asset.Description = m_scene.RegionInfo.RegionName;
1569 asset.Temporary = false;
1570 asset.Flags = AssetFlags.Maptile;
1492 1571
1493 AssetBase asset = new AssetBase( 1572 // Store the new one
1494 terrainImageID, 1573 m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName);
1495 "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(),
1496 (sbyte)AssetType.Texture,
1497 m_scene.RegionInfo.RegionID.ToString());
1498 asset.Data = data;
1499 asset.Description = m_scene.RegionInfo.RegionName;
1500 asset.Temporary = false;
1501 asset.Flags = AssetFlags.Maptile;
1502 1574
1503 // Store the new one 1575 m_scene.AssetService.Store(asset);
1504 m_log.DebugFormat("[WORLD MAP]: Storing map tile {0} for {1}", asset.ID, m_scene.RegionInfo.RegionName);
1505
1506 m_scene.AssetService.Store(asset);
1507 1576
1577 m_scene.RegionInfo.RegionSettings.TerrainImageID = terrainImageID;
1578 needRegionSave = true;
1579 }
1580 }
1581 catch (Exception e)
1582 {
1583 m_log.Error("[WORLD MAP]: Failed generating terrain map: " + e);
1584 }
1585 }
1586
1587 // V2/3 still seem to need this, or we are missing something somewhere
1588 byte[] overlay = GenerateOverlay();
1508 if (overlay != null) 1589 if (overlay != null)
1509 { 1590 {
1510 parcelImageID = UUID.Random(); 1591 UUID parcelImageID = UUID.Random();
1511 1592
1512 AssetBase parcels = new AssetBase( 1593 AssetBase parcels = new AssetBase(
1513 parcelImageID, 1594 parcelImageID,
@@ -1520,20 +1601,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1520 parcels.Flags = AssetFlags.Maptile; 1601 parcels.Flags = AssetFlags.Maptile;
1521 1602
1522 m_scene.AssetService.Store(parcels); 1603 m_scene.AssetService.Store(parcels);
1604
1605 m_scene.RegionInfo.RegionSettings.ParcelImageID = parcelImageID;
1606 needRegionSave = true;
1523 } 1607 }
1524 1608
1525 // Switch to the new one 1609 if (needRegionSave)
1526 UUID lastTerrainImageID = m_scene.RegionInfo.RegionSettings.TerrainImageID; 1610 m_scene.RegionInfo.RegionSettings.Save();
1527 UUID lastParcelImageID = m_scene.RegionInfo.RegionSettings.ParcelImageID;
1528 m_scene.RegionInfo.RegionSettings.TerrainImageID = terrainImageID;
1529 m_scene.RegionInfo.RegionSettings.ParcelImageID = parcelImageID;
1530 m_scene.RegionInfo.RegionSettings.Save();
1531
1532 // Delete the old one
1533 // m_log.DebugFormat("[WORLDMAP]: Deleting old map tile {0}", lastTerrainImageID);
1534 m_scene.AssetService.Delete(lastTerrainImageID.ToString());
1535 if (lastParcelImageID != UUID.Zero)
1536 m_scene.AssetService.Delete(lastParcelImageID.ToString());
1537 } 1611 }
1538 1612
1539 private void MakeRootAgent(ScenePresence avatar) 1613 private void MakeRootAgent(ScenePresence avatar)
@@ -1553,6 +1627,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1553 { 1627 {
1554 m_rootAgents.Remove(avatar.UUID); 1628 m_rootAgents.Remove(avatar.UUID);
1555 } 1629 }
1630
1631 lock (m_mapBlockRequestEvent)
1632 {
1633 if (m_mapBlockRequests.ContainsKey(avatar.UUID))
1634 m_mapBlockRequests.Remove(avatar.UUID);
1635 }
1556 } 1636 }
1557 1637
1558 public void OnRegionUp(GridRegion otherRegion) 1638 public void OnRegionUp(GridRegion otherRegion)
@@ -1562,46 +1642,67 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1562 1642
1563 lock (m_blacklistedregions) 1643 lock (m_blacklistedregions)
1564 { 1644 {
1565 if (!m_blacklistedregions.ContainsKey(regionhandle)) 1645 if (m_blacklistedregions.Contains(regionhandle))
1566 m_blacklistedregions.Remove(regionhandle); 1646 m_blacklistedregions.Remove(regionhandle);
1567 } 1647 }
1568 1648
1569 lock (m_blacklistedurls) 1649 lock (m_blacklistedurls)
1570 { 1650 {
1571 if (m_blacklistedurls.ContainsKey(httpserver)) 1651 if (m_blacklistedurls.Contains(httpserver))
1572 m_blacklistedurls.Remove(httpserver); 1652 m_blacklistedurls.Remove(httpserver);
1573 } 1653 }
1574 1654
1575 lock (m_cachedRegionMapItemsAddress) 1655 lock (m_cachedRegionMapItemsAddress)
1576 { 1656 {
1577 if (!m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) 1657 m_cachedRegionMapItemsAddress.AddOrUpdate(regionhandle,
1578 m_cachedRegionMapItemsAddress.Remove(regionhandle); 1658 httpserver, 5.0 * expireBlackListTime);
1579 } 1659 }
1580 } 1660 }
1581 1661
1582 private Byte[] GenerateOverlay() 1662 private Byte[] GenerateOverlay()
1583 { 1663 {
1664 int landTileSize = LandManagementModule.LandUnit;
1665
1584 // These need to be ints for bitmap generation 1666 // These need to be ints for bitmap generation
1585 int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX; 1667 int regionSizeX = (int)m_scene.RegionInfo.RegionSizeX;
1586 int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY;
1587
1588 int landTileSize = LandManagementModule.LandUnit;
1589 int regionLandTilesX = regionSizeX / landTileSize; 1668 int regionLandTilesX = regionSizeX / landTileSize;
1669
1670 int regionSizeY = (int)m_scene.RegionInfo.RegionSizeY;
1590 int regionLandTilesY = regionSizeY / landTileSize; 1671 int regionLandTilesY = regionSizeY / landTileSize;
1591 1672
1592 using (Bitmap overlay = new Bitmap(regionSizeX, regionSizeY)) 1673 bool landForSale = false;
1674 ILandObject land;
1675
1676 // scan terrain avoiding potencial merges of large bitmaps
1677 //TODO create the sell bitmap at landchannel / landmaster ?
1678 // and auction also, still not suported
1679
1680 bool[,] saleBitmap = new bool[regionLandTilesX, regionLandTilesY];
1681 for (int x = 0, xx = 0; x < regionLandTilesX; x++ ,xx += landTileSize)
1593 { 1682 {
1594 bool[,] saleBitmap = new bool[regionLandTilesX, regionLandTilesY]; 1683 for (int y = 0, yy = 0; y < regionLandTilesY; y++, yy += landTileSize)
1595 for (int x = 0; x < regionLandTilesX; x++)
1596 { 1684 {
1597 for (int y = 0; y < regionLandTilesY; y++) 1685 land = m_scene.LandChannel.GetLandObject(xx, yy);
1686 if (land != null && (land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1687 {
1688 saleBitmap[x, y] = true;
1689 landForSale = true;
1690 }
1691 else
1598 saleBitmap[x, y] = false; 1692 saleBitmap[x, y] = false;
1599 } 1693 }
1694 }
1600 1695
1601 bool landForSale = false; 1696 if (!landForSale)
1697 {
1698 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1699 return null;
1700 }
1602 1701
1603 List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); 1702 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1604 1703
1704 using (Bitmap overlay = new Bitmap(regionSizeX, regionSizeY))
1705 {
1605 Color background = Color.FromArgb(0, 0, 0, 0); 1706 Color background = Color.FromArgb(0, 0, 0, 0);
1606 1707
1607 using (Graphics g = Graphics.FromImage(overlay)) 1708 using (Graphics g = Graphics.FromImage(overlay))
@@ -1609,36 +1710,19 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1609 using (SolidBrush transparent = new SolidBrush(background)) 1710 using (SolidBrush transparent = new SolidBrush(background))
1610 g.FillRectangle(transparent, 0, 0, regionSizeX, regionSizeY); 1711 g.FillRectangle(transparent, 0, 0, regionSizeX, regionSizeY);
1611 1712
1612 foreach (ILandObject land in parcels) 1713 // make it a bit transparent
1714 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(192, 249, 223, 9)))
1613 { 1715 {
1614 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags); 1716 for (int x = 0; x < regionLandTilesX; x++)
1615 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1616 { 1717 {
1617 landForSale = true; 1718 for (int y = 0; y < regionLandTilesY; y++)
1618
1619 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap());
1620 }
1621 }
1622
1623 if (!landForSale)
1624 {
1625 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1626 return null;
1627 }
1628
1629 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1630
1631 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)))
1632 {
1633 for (int x = 0 ; x < regionLandTilesX ; x++)
1634 {
1635 for (int y = 0 ; y < regionLandTilesY ; y++)
1636 { 1719 {
1637 if (saleBitmap[x, y]) 1720 if (saleBitmap[x, y])
1638 g.FillRectangle( 1721 g.FillRectangle(
1639 yellow, x * landTileSize, 1722 yellow,
1640 regionSizeX - landTileSize - (y * landTileSize), 1723 x * landTileSize,
1641 landTileSize, 1724 regionSizeX - landTileSize - (y * landTileSize),
1725 landTileSize,
1642 landTileSize); 1726 landTileSize);
1643 } 1727 }
1644 } 1728 }
@@ -1659,7 +1743,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1659 } 1743 }
1660 } 1744 }
1661 1745
1662 public struct MapRequestState 1746 public class MapRequestState
1663 { 1747 {
1664 public UUID agentID; 1748 public UUID agentID;
1665 public uint flags; 1749 public uint flags;
@@ -1668,4 +1752,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1668 public uint itemtype; 1752 public uint itemtype;
1669 public ulong regionhandle; 1753 public ulong regionhandle;
1670 } 1754 }
1755
1756 public struct MapBlockRequestData
1757 {
1758 public IClientAPI client;
1759 public int minX;
1760 public int minY;
1761 public int maxX;
1762 public int maxY;
1763 public uint flags;
1764 }
1671} 1765}
diff --git a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
index 0cc8fb6..e0aad2b 100644
--- a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Framework.Interfaces
36 void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID, 36 void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID,
37 InventoryItemBase item); 37 InventoryItemBase item);
38 38
39 void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID, 39 bool HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID,
40 uint callbackID, string description, string name, sbyte invType, 40 uint callbackID, string description, string name, sbyte invType,
41 sbyte type, byte wearableType, uint nextOwnerMask); 41 sbyte type, byte wearableType, uint nextOwnerMask);
42 42
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index d9901bd..3c1247f 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -89,7 +90,7 @@ namespace OpenSim.Region.Framework.Interfaces
89 /// <param name="addToInventory">If true then add object to user inventory</param> 90 /// <param name="addToInventory">If true then add object to user inventory</param>
90 /// <param name="append">Append to attachment point rather than replace.</param> 91 /// <param name="append">Append to attachment point rather than replace.</param>
91 /// <returns>true if the object was successfully attached, false otherwise</returns> 92 /// <returns>true if the object was successfully attached, false otherwise</returns>
92 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool addToInventory, bool append); 93 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool addToInventory, bool append);
93 94
94 /// <summary> 95 /// <summary>
95 /// Rez an attachment from user inventory and change inventory status to match. 96 /// Rez an attachment from user inventory and change inventory status to match.
@@ -98,7 +99,11 @@ namespace OpenSim.Region.Framework.Interfaces
98 /// <param name="itemID"></param> 99 /// <param name="itemID"></param>
99 /// <param name="AttachmentPt"></param> 100 /// <param name="AttachmentPt"></param>
100 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 101 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
101 SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 102 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
103
104 // Same as above, but also load script states from a separate doc
105 ISceneEntity RezSingleAttachmentFromInventory(
106 IScenePresence presence, UUID itemID, uint AttachmentPt, XmlDocument doc);
102 107
103 /// <summary> 108 /// <summary>
104 /// Rez multiple attachments from a user's inventory 109 /// Rez multiple attachments from a user's inventory
@@ -130,7 +135,6 @@ namespace OpenSim.Region.Framework.Interfaces
130 /// <param name="grp">The attachment to detach.</param> 135 /// <param name="grp">The attachment to detach.</param>
131 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp); 136 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp);
132 137
133 /// <summary>
134 /// Update the position of an attachment. 138 /// Update the position of an attachment.
135 /// </summary> 139 /// </summary>
136 /// <param name="sog"></param> 140 /// <param name="sog"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
index b536a49..4d8409be 100644
--- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
@@ -35,6 +35,9 @@ namespace OpenSim.Services.Interfaces
35 public interface IBakedTextureModule 35 public interface IBakedTextureModule
36 { 36 {
37 WearableCacheItem[] Get(UUID id); 37 WearableCacheItem[] Get(UUID id);
38 void Store(UUID id, WearableCacheItem[] data); 38
39 void Store(UUID id);
40 void Store(UUID id, WearableCacheItem[] WearableCache);
41 void UpdateMeshAvatar(UUID id);
39 } 42 }
40} 43}
diff --git a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
index 522c82d..30d404e 100644
--- a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
@@ -40,19 +40,19 @@ namespace OpenSim.Region.Framework.Interfaces
40 /// </summary> 40 /// </summary>
41 /// <param name="agentId"></param> 41 /// <param name="agentId"></param>
42 /// <param name="capsObjectPath"></param> 42 /// <param name="capsObjectPath"></param>
43 void CreateCaps(UUID agentId); 43 void CreateCaps(UUID agentId, uint circuitCode);
44 44
45 /// <summary> 45 /// <summary>
46 /// Remove the caps handler for a given agent. 46 /// Remove the caps handler for a given agent.
47 /// </summary> 47 /// </summary>
48 /// <param name="agentId"></param> 48 /// <param name="agentId"></param>
49 void RemoveCaps(UUID agentId); 49 void RemoveCaps(UUID agentId, uint circuitCode);
50 50
51 /// <summary> 51 /// <summary>
52 /// Will return null if the agent doesn't have a caps handler registered 52 /// Will return null if the agent doesn't have a caps handler registered
53 /// </summary> 53 /// </summary>
54 /// <param name="agentId"></param> 54 /// <param name="agentId"></param>
55 Caps GetCapsForUser(UUID agentId); 55 Caps GetCapsForUser(uint circuitCode);
56 56
57 void SetAgentCapsSeeds(AgentCircuitData agent); 57 void SetAgentCapsSeeds(AgentCircuitData agent);
58 58
@@ -65,5 +65,7 @@ namespace OpenSim.Region.Framework.Interfaces
65 void DropChildSeed(UUID agentID, ulong handle); 65 void DropChildSeed(UUID agentID, ulong handle);
66 66
67 string GetCapsPath(UUID agentId); 67 string GetCapsPath(UUID agentId);
68
69 void ActivateCaps(uint circuitCode);
68 } 70 }
69} 71}
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs b/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
index 08b71e4..4d000b6 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
@@ -43,6 +43,7 @@ namespace OpenSim.Region.Framework.Interfaces
43 public enum UserMode : int 43 public enum UserMode : int
44 { 44 {
45 Normal = 0, 45 Normal = 0,
46 RegionManager = 2,
46 God = 3 47 God = 3
47 } 48 }
48 49
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 9ffda51..b85fd8b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -133,6 +133,8 @@ namespace OpenSim.Region.Framework.Interfaces
133 /// </returns> 133 /// </returns>
134 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 134 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
135 135
136 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
137
136 /// <summary> 138 /// <summary>
137 /// Stop and remove a script which is in this prim's inventory from the scene. 139 /// Stop and remove a script which is in this prim's inventory from the scene.
138 /// </summary> 140 /// </summary>
@@ -244,7 +246,7 @@ namespace OpenSim.Region.Framework.Interfaces
244 /// <param name="objlist">The scene objects</param> 246 /// <param name="objlist">The scene objects</param>
245 /// <param name="veclist">Relative offsets for each object</param> 247 /// <param name="veclist">Relative offsets for each object</param>
246 /// <returns>true = success, false = the scene object asset couldn't be found</returns> 248 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
247 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist); 249 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight);
248 250
249 /// <summary> 251 /// <summary>
250 /// Update an existing inventory item. 252 /// Update an existing inventory item.
@@ -318,5 +320,6 @@ namespace OpenSim.Region.Framework.Interfaces
318 /// A <see cref="Dictionary`2"/> 320 /// A <see cref="Dictionary`2"/>
319 /// </returns> 321 /// </returns>
320 Dictionary<UUID, string> GetScriptStates(); 322 Dictionary<UUID, string> GetScriptStates();
323 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
321 } 324 }
322} 325}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index d07b15a..d172780 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -36,6 +36,7 @@ using OpenSim.Region.Framework.Scenes;
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx); 38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx);
39 public delegate ScenePresence CrossAsyncDelegate(ScenePresence agent, bool isFlying);
39 40
40 public interface IEntityTransferModule 41 public interface IEntityTransferModule
41 { 42 {
@@ -94,8 +95,10 @@ namespace OpenSim.Region.Framework.Interfaces
94 95
95 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx, 96 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx,
96 out Vector3 newpos, out string reason); 97 out Vector3 newpos, out string reason);
98 GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos);
99 bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, EntityTransferContext ctx, out string reason);
97 100
98 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 101 bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent, bool removeScripts);
99 102
100 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx); 103 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx);
101 104
diff --git a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
index 124504c..efc9ddc 100644
--- a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
+++ b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
@@ -58,7 +58,6 @@ namespace OpenSim.Region.Framework.Interfaces
58 public interface IHttpRequestModule 58 public interface IHttpRequestModule
59 { 59 {
60 UUID MakeHttpRequest(string url, string parameters, string body); 60 UUID MakeHttpRequest(string url, string parameters, string body);
61
62 /// <summary> 61 /// <summary>
63 /// Starts the http request. 62 /// Starts the http request.
64 /// </summary> 63 /// </summary>
@@ -85,8 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
85 /// Stop and remove all http requests for the given script. 84 /// Stop and remove all http requests for the given script.
86 /// </summary> 85 /// </summary>
87 /// <param name='id'></param> 86 /// <param name='id'></param>
88 void StopHttpRequestsForScript(UUID id); 87 void StopHttpRequest(uint m_localID, UUID m_itemID);
89
90 IServiceRequest GetNextCompletedRequest(); 88 IServiceRequest GetNextCompletedRequest();
91 void RemoveCompletedRequest(UUID id); 89 void RemoveCompletedRequest(UUID id);
92 } 90 }
diff --git a/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs b/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
index 6a7d4a1..5151567 100644
--- a/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
@@ -25,13 +25,18 @@
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.Drawing; 28using OpenMetaverse;
29using OpenSim.Framework; 29using OpenSim.Framework;
30using System.Drawing;
30 31
31namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
32{ 33{
33 public interface IMapImageUploadModule 34 public interface IMapImageUploadModule
34 { 35 {
36 /// <summary>
37 /// Upload a new maptile
38 /// </summary>
39 void UploadMapTile(IScene scene);
35 void UploadMapTile(IScene scene, Bitmap mapTile); 40 void UploadMapTile(IScene scene, Bitmap mapTile);
36 } 41 }
37} \ No newline at end of file 42}
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index 478833e..8f9a13c 100644
--- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -31,6 +31,16 @@ using OpenSim.Region.Framework.Scenes;
31 31
32namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
33{ 33{
34 // option flags for NPCs
35 public enum NPCOptionsFlags : int
36 {
37 None = 0x00, // no flags (max restriction)
38 AllowNotOwned = 0x01, // allow NPCs to be created not Owned
39 AllowSenseAsAvatar = 0x02, // allow NPCs to set to be sensed as Avatars
40 AllowCloneOtherAvatars = 0x04, // allow NPCs to created cloning a avatar in region
41 NoNPCGroup = 0x08 // NPCs will have no group title, otherwise will have "- NPC -"
42 }
43
34 /// <summary> 44 /// <summary>
35 /// Temporary interface. More methods to come at some point to make NPCs 45 /// Temporary interface. More methods to come at some point to make NPCs
36 /// more object oriented rather than controlling purely through module 46 /// more object oriented rather than controlling purely through module
@@ -284,5 +294,7 @@ namespace OpenSim.Region.Framework.Interfaces
284 /// agent, the agent is unowned or the agent was not an NPC. 294 /// agent, the agent is unowned or the agent was not an NPC.
285 /// </returns> 295 /// </returns>
286 UUID GetOwner(UUID agentID); 296 UUID GetOwner(UUID agentID);
297
298 NPCOptionsFlags NPCOptionFlags {get;}
287 } 299 }
288} 300}
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
index 4d261d6..5d5ce34 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
@@ -30,8 +30,12 @@ using OpenSim.Framework;
30 30
31namespace OpenSim.Region.Framework.Interfaces 31namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public delegate void ConsoleMessage(UUID toAgentID, string message);
34
33 public interface IRegionConsole 35 public interface IRegionConsole
34 { 36 {
37 event ConsoleMessage OnConsoleMessage;
38
35 bool RunCommand(string command, UUID invokerID); 39 bool RunCommand(string command, UUID invokerID);
36 void SendConsoleOutput(UUID agentID, string message); 40 void SendConsoleOutput(UUID agentID, string message);
37 void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn); 41 void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn);
diff --git a/OpenSim/Region/Framework/Interfaces/IRestartModule.cs b/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
index c68550f..9b25beb 100644
--- a/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
@@ -35,5 +35,6 @@ namespace OpenSim.Region.Framework.Interfaces
35 TimeSpan TimeUntilRestart { get; } 35 TimeSpan TimeUntilRestart { get; }
36 void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice); 36 void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice);
37 void AbortRestart(string message); 37 void AbortRestart(string message);
38 void DelayRestart(int seconds, string message);
38 } 39 }
39} 40}
diff --git a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
index 64bf72c..d56d188 100644
--- a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
@@ -31,6 +31,6 @@ namespace OpenSim.Framework
31{ 31{
32 public interface ISearchModule 32 public interface ISearchModule
33 { 33 {
34 34 void Refresh();
35 } 35 }
36} 36}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 8948f04..13358cb 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -125,6 +125,8 @@ namespace OpenSim.Region.Framework.Interfaces
125 /// <param name="regionUUID">the region UUID</param> 125 /// <param name="regionUUID">the region UUID</param>
126 void RemoveRegionEnvironmentSettings(UUID regionUUID); 126 void RemoveRegionEnvironmentSettings(UUID regionUUID);
127 127
128 UUID[] GetObjectIDs(UUID regionID);
129
128 void SaveExtra(UUID regionID, string name, string value); 130 void SaveExtra(UUID regionID, string name, string value);
129 131
130 void RemoveExtra(UUID regionID, string name); 132 void RemoveExtra(UUID regionID, string name);
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 917b5d1..e09f775 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -115,6 +115,7 @@ namespace OpenSim.Region.Framework.Interfaces
115 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID); 115 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID);
116 void StoreRegionWindlightSettings(RegionLightShareData wl); 116 void StoreRegionWindlightSettings(RegionLightShareData wl);
117 void RemoveRegionWindlightSettings(UUID regionID); 117 void RemoveRegionWindlightSettings(UUID regionID);
118 UUID[] GetObjectIDs(UUID regionID);
118 119
119 /// <summary> 120 /// <summary>
120 /// Load Environment settings from region storage 121 /// Load Environment settings from region storage
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..f805863
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.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 OpenSim.Region.Framework.Scenes;
29
30public interface ISnmpModule
31{
32 void Trap(int code, string Message, Scene scene);
33 void Critical(string Message, Scene scene);
34 void Warning(string Message, Scene scene);
35 void Major(string Message, Scene scene);
36 void ColdStart(int step , Scene scene);
37 void Shutdown(int step , Scene scene);
38 //
39 // Node Start/stop events
40 //
41 void LinkUp(Scene scene);
42 void LinkDown(Scene scene);
43 void BootInfo(string data, Scene scene);
44 void trapDebug(string Module,string data, Scene scene);
45 void trapXMRE(int data, string Message, Scene scene);
46
47}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 8372ddd..f7c6513 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -95,7 +95,7 @@ namespace OpenSim.Region.Framework.Interfaces
95 /// <param name="radius">Sound radius</param> 95 /// <param name="radius">Sound radius</param>
96 /// <param name="isMaster">Set object to sync master if true</param> 96 /// <param name="isMaster">Set object to sync master if true</param>
97 void LoopSound(UUID objectID, UUID soundID, double gain, 97 void LoopSound(UUID objectID, UUID soundID, double gain,
98 double radius, bool isMaster); 98 double radius, bool isMaster, bool isSlave);
99 99
100 /// <summary> 100 /// <summary>
101 /// Trigger or play an attached sound in this part's inventory. 101 /// Trigger or play an attached sound in this part's inventory.
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
index 28f797a..472e5a5d 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
@@ -28,6 +28,8 @@ using System.IO;
28 28
29using OpenSim.Framework; 29using OpenSim.Framework;
30 30
31using System.IO;
32using OpenSim.Framework;
31using OpenMetaverse; 33using OpenMetaverse;
32 34
33namespace OpenSim.Region.Framework.Interfaces 35namespace OpenSim.Region.Framework.Interfaces
@@ -43,13 +45,13 @@ namespace OpenSim.Region.Framework.Interfaces
43 /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight) 45 /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight)
44 /// </summary> 46 /// </summary>
45 void TaintTerrain(); 47 void TaintTerrain();
46 48
47 /// <summary> 49 /// <summary>
48 /// When a client initially connects, all the terrain must be pushed to the viewer. 50 /// When a client initially connects, all the terrain must be pushed to the viewer.
49 /// This call causes all the terrain patches to be sent to the client. 51 /// This call causes all the terrain patches to be sent to the client.
50 /// </summary> 52 /// </summary>
51 void PushTerrain(IClientAPI pClient); 53 void PushTerrain(IClientAPI pClient);
52 54
53 /// <summary> 55 /// <summary>
54 /// Load a terrain from a stream. 56 /// Load a terrain from a stream.
55 /// </summary> 57 /// </summary>
@@ -58,8 +60,9 @@ namespace OpenSim.Region.Framework.Interfaces
58 /// </param> 60 /// </param>
59 /// <param name="stream"></param> 61 /// <param name="stream"></param>
60 void LoadFromStream(string filename, Stream stream); 62 void LoadFromStream(string filename, Stream stream);
61 void LoadFromStream(string filename, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement, Stream stream);
62 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap); 63 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
64 void LoadFromStream(string filename, Vector3 displacement,
65 float radianRotation, Vector2 rotationDisplacement, Stream stream);
63 /// <summary> 66 /// <summary>
64 /// Save a terrain to a stream. 67 /// Save a terrain to a stream.
65 /// </summary> 68 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..ed26989
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,33 @@
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 OpenSim.Region.Framework.Scenes;
29
30public interface IUserAccountCacheModule
31{
32 void Remove(string name);
33}
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index d76a0d7..c01c56d 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -127,7 +127,7 @@ namespace OpenSim.Region.Framework.Interfaces
127 /// <param name='msg'> 127 /// <param name='msg'>
128 /// Message. 128 /// Message.
129 /// </param> 129 /// </param>
130 void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg); 130 bool DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg);
131 131
132 /// <summary> 132 /// <summary>
133 /// Are there any listen events ready to be dispatched? 133 /// Are there any listen events ready to be dispatched?
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs b/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
index 9c781e1..ee7c4ec 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
@@ -36,7 +36,6 @@ namespace OpenSim.Region.Framework.Interfaces
36 /// Generate a map tile for the scene. a terrain texture for this scene 36 /// Generate a map tile for the scene. a terrain texture for this scene
37 /// </summary> 37 /// </summary>
38 void GenerateMaptile(); 38 void GenerateMaptile();
39 List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag); 39 void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag);
40 MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag);
41 } 40 }
42} 41}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
new file mode 100644
index 0000000..d59678b
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
@@ -0,0 +1,101 @@
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.Xml;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Threading;
33using System.Timers;
34using Timer = System.Timers.Timer;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38using OpenSim.Framework;
39using OpenSim.Framework.Client;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes.Animation;
42using OpenSim.Region.Framework.Scenes.Types;
43using OpenSim.Region.PhysicsModules.SharedBase;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45using OpenSim.Services.Interfaces;
46using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
47
48namespace OpenSim.Region.Framework.Scenes
49{
50 public class MovementAnimationOverrides
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private Dictionary<string, UUID> m_overrides = new Dictionary<string, UUID>();
56 public void SetOverride(string state, UUID animID)
57 {
58 if (animID == UUID.Zero)
59 {
60 if (state == "ALL")
61 m_overrides.Clear();
62 else
63 m_overrides.Remove(state);
64 return;
65 }
66
67 m_log.DebugFormat("Setting override for {0} to {1}", state, animID);
68
69 lock (m_overrides)
70 m_overrides[state] = animID;
71 }
72
73 public UUID GetOverriddenAnimation(string state)
74 {
75 lock (m_overrides)
76 {
77 if (m_overrides.ContainsKey(state))
78 return m_overrides[state];
79 }
80
81 return UUID.Zero;
82 }
83
84 public Dictionary<string, UUID> CloneAOPairs()
85 {
86 lock (m_overrides)
87 {
88 return new Dictionary<string, UUID>(m_overrides);
89 }
90 }
91
92 public void CopyAOPairsFrom(Dictionary<string, UUID> src)
93 {
94 lock (m_overrides)
95 {
96 m_overrides.Clear();
97 m_overrides = new Dictionary<string, UUID>(src);
98 }
99 }
100 }
101}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 6d51029..13d4562 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
48 48
49 public AnimationSet Animations 49 public AnimationSet Animations
50 { 50 {
51 get { return m_animations; } 51 get { return m_animations; }
52 } 52 }
53 protected AnimationSet m_animations = new AnimationSet(); 53 protected AnimationSet m_animations = new AnimationSet();
54 54
@@ -56,39 +56,42 @@ namespace OpenSim.Region.Framework.Scenes.Animation
56 /// The current movement animation 56 /// The current movement animation
57 /// </value> 57 /// </value>
58 public string CurrentMovementAnimation { get; private set; } 58 public string CurrentMovementAnimation { get; private set; }
59 59
60 private int m_animTickFall; 60 private int m_animTickFall;
61 public int m_animTickJump; // ScenePresence has to see this to control +Z force 61 private int m_animTickLand;
62 public bool m_jumping = false; 62 private int m_animTickJump;
63 public float m_jumpVelocity = 0f; 63
64// private int m_landing = 0; 64 public bool m_jumping = false;
65
66 // private int m_landing = 0;
65 67
66 /// <summary> 68 /// <summary>
67 /// Is the avatar falling? 69 /// Is the avatar falling?
68 /// </summary> 70 /// </summary>
69 public bool Falling { get; private set; } 71 public bool Falling { get; private set; }
70 72
71 private float m_fallHeight; 73 private float m_lastFallVelocity;
72 74
73 /// <value> 75 /// <value>
74 /// The scene presence that this animator applies to 76 /// The scene presence that this animator applies to
75 /// </value> 77 /// </value>
76 protected ScenePresence m_scenePresence; 78 protected ScenePresence m_scenePresence;
77 79
78 public ScenePresenceAnimator(ScenePresence sp) 80 public ScenePresenceAnimator(ScenePresence sp)
79 { 81 {
80 m_scenePresence = sp; 82 m_scenePresence = sp;
81 CurrentMovementAnimation = "CROUCH"; 83 CurrentMovementAnimation = "CROUCH";
82 } 84 }
83 85
84 public void AddAnimation(UUID animID, UUID objectID) 86 public void AddAnimation(UUID animID, UUID objectID)
85 { 87 {
86 if (m_scenePresence.IsChildAgent) 88 if (m_scenePresence.IsChildAgent)
87 return; 89 return;
88 90
91 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name);
89 if (m_scenePresence.Scene.DebugAnimations) 92 if (m_scenePresence.Scene.DebugAnimations)
90 m_log.DebugFormat( 93 m_log.DebugFormat(
91 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", 94 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}",
92 GetAnimName(animID), animID, m_scenePresence.Name); 95 GetAnimName(animID), animID, m_scenePresence.Name);
93 96
94 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 97 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
@@ -110,7 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
110 if (animID == UUID.Zero) 113 if (animID == UUID.Zero)
111 return; 114 return;
112 115
113// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name); 116 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name);
114 117
115 AddAnimation(animID, objectID); 118 AddAnimation(animID, objectID);
116 } 119 }
@@ -130,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
130 133
131 if (m_scenePresence.Scene.DebugAnimations) 134 if (m_scenePresence.Scene.DebugAnimations)
132 m_log.DebugFormat( 135 m_log.DebugFormat(
133 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}", 136 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}",
134 GetAnimName(animID), animID, m_scenePresence.Name); 137 GetAnimName(animID), animID, m_scenePresence.Name);
135 138
136 if (m_animations.Remove(animID, allowNoDefault)) 139 if (m_animations.Remove(animID, allowNoDefault))
@@ -140,6 +143,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation
140 } 143 }
141 } 144 }
142 145
146 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
147 {
148 if (m_scenePresence.IsChildAgent)
149 return;
150
151 if (animID != UUID.Zero)
152 {
153 if (addRemove)
154 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero);
155 else
156 m_animations.Remove(animID, false);
157 }
158 if (sendPack)
159 SendAnimPack();
160 }
161
143 // Called from scripts 162 // Called from scripts
144 public void RemoveAnimation(string name) 163 public void RemoveAnimation(string name)
145 { 164 {
@@ -164,12 +183,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation
164 183
165 m_animations.Clear(); 184 m_animations.Clear();
166 } 185 }
167 186
187
188 UUID aoSitGndAnim = UUID.Zero;
189
168 /// <summary> 190 /// <summary>
169 /// The movement animation is reserved for "main" animations 191 /// The movement animation is reserved for "main" animations
170 /// that are mutually exclusive, e.g. flying and sitting. 192 /// that are mutually exclusive, e.g. flying and sitting.
171 /// </summary> 193 /// </summary>
172 /// <returns>'true' if the animation was updated</returns> 194 /// <returns>'true' if the animation was updated</returns>
195 ///
196
197
198
173 public bool TrySetMovementAnimation(string anim) 199 public bool TrySetMovementAnimation(string anim)
174 { 200 {
175 bool ret = false; 201 bool ret = false;
@@ -179,17 +205,50 @@ namespace OpenSim.Region.Framework.Scenes.Animation
179// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}", 205// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}",
180// anim, m_scenePresence.Name); 206// anim, m_scenePresence.Name);
181 207
182 if (m_animations.TrySetDefaultAnimation( 208 if (aoSitGndAnim != UUID.Zero)
183 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) 209 {
210 avnChangeAnim(aoSitGndAnim, false, true);
211 aoSitGndAnim = UUID.Zero;
212 }
213
214 UUID overridenAnim = m_scenePresence.Overrides.GetOverriddenAnimation(anim);
215 if (overridenAnim != UUID.Zero)
184 { 216 {
217 if (anim == "SITGROUND")
218 {
219 UUID defsit = DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"];
220 if (defsit == UUID.Zero)
221 return false;
222 m_animations.SetDefaultAnimation(defsit, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID);
223 aoSitGndAnim = overridenAnim;
224 avnChangeAnim(overridenAnim, true, false);
225 }
226 else
227 {
228 m_animations.SetDefaultAnimation(overridenAnim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID);
229 }
230 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION });
231 SendAnimPack();
232 ret = true;
233 }
234 else
235 {
236 // translate sit and sitground state animations
237 if (anim == "SIT" || anim == "SITGROUND")
238 anim = m_scenePresence.sitAnimation;
239
240 if (m_animations.TrySetDefaultAnimation(
241 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID))
242 {
185// m_log.DebugFormat( 243// m_log.DebugFormat(
186// "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}", 244// "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}",
187// anim, m_scenePresence.Name); 245// anim, m_scenePresence.Name);
188 246
189 // 16384 is CHANGED_ANIMATION 247 // 16384 is CHANGED_ANIMATION
190 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); 248 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION });
191 SendAnimPack(); 249 SendAnimPack();
192 ret = true; 250 ret = true;
251 }
193 } 252 }
194 } 253 }
195 else 254 else
@@ -201,78 +260,119 @@ namespace OpenSim.Region.Framework.Scenes.Animation
201 return ret; 260 return ret;
202 } 261 }
203 262
263 public enum motionControlStates : byte
264 {
265 sitted = 0,
266 flying,
267 falling,
268 jumping,
269 landing,
270 onsurface
271 }
272
273 public motionControlStates currentControlState = motionControlStates.onsurface;
274
204 /// <summary> 275 /// <summary>
205 /// This method determines the proper movement related animation 276 /// This method determines the proper movement related animation
206 /// </summary> 277 /// </summary>
207 private string DetermineMovementAnimation() 278 private string DetermineMovementAnimation()
208 { 279 {
209 const float FALL_DELAY = 800f; 280 const int FALL_DELAY = 800;
210 const float PREJUMP_DELAY = 200f; 281 const int PREJUMP_DELAY = 200;
211 const float JUMP_PERIOD = 800f; 282 const int JUMP_PERIOD = 800;
212 #region Inputs 283 #region Inputs
213 284
285 if (m_scenePresence.IsInTransit)
286 return CurrentMovementAnimation;
287
288 if (m_scenePresence.SitGround)
289 {
290 currentControlState = motionControlStates.sitted;
291 return "SITGROUND";
292 }
293 if (m_scenePresence.ParentID != 0 || m_scenePresence.ParentUUID != UUID.Zero)
294 {
295 currentControlState = motionControlStates.sitted;
296 return "SIT";
297 }
298
214 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 299 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
215 PhysicsActor actor = m_scenePresence.PhysicsActor; 300 PhysicsActor actor = m_scenePresence.PhysicsActor;
216 301
217 // Create forward and left vectors from the current avatar rotation 302 const AgentManager.ControlFlags ANYXYMASK = (
218 Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation); 303 AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS |
219 Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix); 304 AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG |
220 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 305 AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS |
306 AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG
307 );
221 308
222 // Check control flags 309 // Check control flags
223 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); 310 /* not in use
224 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); 311 bool heldForward = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)) != 0);
225 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); 312 bool heldBack = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG)) != 0);
226 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG); 313 bool heldLeft = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS)) != 0);
314 bool heldRight = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG)) != 0);
315 */
227 bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 316 bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
228 bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 317 bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
229 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 318 // bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS)) != 0);
230 bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG; 319 // excluded nudge up so it doesn't trigger jump state
320 bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS)) != 0);
321 bool heldDown = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG)) != 0);
231 //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY; 322 //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
232 //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK; 323 //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
233 if (heldForward || heldBack || heldLeft || heldRight || heldUp || heldDown) 324
325 bool heldOnXY = ((controlFlags & ANYXYMASK) != 0);
326 if (heldOnXY || heldUp || heldDown)
234 { 327 {
235 heldTurnLeft = false; 328 heldTurnLeft = false;
236 heldTurnRight = false; 329 heldTurnRight = false;
237 } 330 }
238 331
239 // Direction in which the avatar is trying to move
240 Vector3 move = Vector3.Zero;
241 if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
242 if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
243 if (heldLeft) { move.X += left.X; move.Y += left.Y; }
244 if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
245 if (heldUp) { move.Z += 1; }
246 if (heldDown) { move.Z -= 1; }
247
248 // Is the avatar trying to move?
249// bool moving = (move != Vector3.Zero);
250 #endregion Inputs 332 #endregion Inputs
251 333
334 // no physics actor case
335 if (actor == null)
336 {
337 // well what to do?
338
339 currentControlState = motionControlStates.onsurface;
340 if (heldOnXY)
341 return "WALK";
342
343 return "STAND";
344 }
345
252 #region Flying 346 #region Flying
253 347
254 if (actor != null && actor.Flying) 348 bool isColliding = actor.IsColliding;
349
350 if (actor.Flying)
255 { 351 {
256 m_animTickFall = 0; 352 m_animTickFall = 0;
257 m_animTickJump = 0; 353 m_animTickJump = 0;
258 m_jumping = false; 354 m_jumping = false;
259 Falling = false; 355 Falling = false;
260 m_jumpVelocity = 0f;
261 actor.Selected = false;
262 m_fallHeight = actor.Position.Z; // save latest flying height
263 356
264 if (move.X != 0f || move.Y != 0f) 357 currentControlState = motionControlStates.flying;
358
359 if (heldOnXY)
265 { 360 {
266 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); 361 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
267 } 362 }
268 else if (move.Z > 0f) 363 else if (heldUp)
269 { 364 {
270 return "HOVER_UP"; 365 return "HOVER_UP";
271 } 366 }
272 else if (move.Z < 0f) 367 else if (heldDown)
273 { 368 {
274 if (actor != null && actor.IsColliding) 369 if (isColliding)
370 {
371 actor.Flying = false;
372 currentControlState = motionControlStates.landing;
373 m_animTickLand = Environment.TickCount;
275 return "LAND"; 374 return "LAND";
375 }
276 else 376 else
277 return "HOVER_DOWN"; 377 return "HOVER_DOWN";
278 } 378 }
@@ -281,128 +381,151 @@ namespace OpenSim.Region.Framework.Scenes.Animation
281 return "HOVER"; 381 return "HOVER";
282 } 382 }
283 } 383 }
384 else
385 {
386 if (isColliding && currentControlState == motionControlStates.flying)
387 {
388 currentControlState = motionControlStates.landing;
389 m_animTickLand = Environment.TickCount;
390 return "LAND";
391 }
392 }
284 393
285 #endregion Flying 394 #endregion Flying
286 395
287 #region Falling/Floating/Landing 396 #region Falling/Floating/Landing
288 397
289 if ((actor == null || !actor.IsColliding) && !m_jumping) 398 if (!isColliding && currentControlState != motionControlStates.jumping)
290 { 399 {
291 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); 400 float fallVelocity = actor.Velocity.Z;
292 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
293 401
294 if (!m_jumping && (fallVelocity < -3.0f)) 402 // if stable on Hover assume falling
403 if(actor.PIDHoverActive && fallVelocity < 0.05f)
404 {
405 Falling = true;
406 currentControlState = motionControlStates.falling;
407 m_lastFallVelocity = fallVelocity;
408 return "FALLDOWN";
409 }
410
411 if (fallVelocity < -2.5f)
295 Falling = true; 412 Falling = true;
296 413
297 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) 414 if (m_animTickFall == 0 || (fallVelocity >= -0.5f))
298 { 415 {
299 // not falling yet, or going up
300 // reset start of fall time
301 m_animTickFall = Environment.TickCount; 416 m_animTickFall = Environment.TickCount;
302 } 417 }
303 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying)) 418 else
304 { 419 {
305 // Falling long enough to trigger the animation 420 int fallElapsed = (Environment.TickCount - m_animTickFall);
306 return "FALLDOWN"; 421 if ((fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f))
422 {
423 currentControlState = motionControlStates.falling;
424 m_lastFallVelocity = fallVelocity;
425 // Falling long enough to trigger the animation
426 return "FALLDOWN";
427 }
307 } 428 }
308 429
309 // Check if the user has stopped walking just now 430 // Check if the user has stopped walking just now
310 if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero)) 431 if (CurrentMovementAnimation == "WALK" && !heldOnXY && !heldDown && !heldUp)
311 return "STAND"; 432 return "STAND";
312 433
313 return CurrentMovementAnimation; 434 return CurrentMovementAnimation;
314 } 435 }
315 436
316 #endregion Falling/Floating/Landing 437 m_animTickFall = 0;
317 438
439 #endregion Falling/Floating/Landing
318 440
319 #region Jumping // section added for jumping... 441 #region Jumping // section added for jumping...
320 442
321 int jumptime; 443 if (isColliding && heldUp && currentControlState != motionControlStates.jumping && !actor.PIDHoverActive)
322 jumptime = Environment.TickCount - m_animTickJump;
323
324 if ((move.Z > 0f) && (!m_jumping))
325 { 444 {
326 // Start jumping, prejump 445 // Start jumping, prejump
327 m_animTickFall = 0; 446 currentControlState = motionControlStates.jumping;
328 m_jumping = true; 447 m_jumping = true;
329 Falling = false; 448 Falling = false;
330 actor.Selected = true; // borrowed for jumping flag
331 m_animTickJump = Environment.TickCount; 449 m_animTickJump = Environment.TickCount;
332 m_jumpVelocity = 0.35f;
333 return "PREJUMP"; 450 return "PREJUMP";
334 } 451 }
335 452
336 if (m_jumping) 453 if (currentControlState == motionControlStates.jumping)
337 { 454 {
455 int jumptime = Environment.TickCount - m_animTickJump;
338 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) 456 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
339 { 457 {
340 // end jumping 458 // end jumping
341 m_jumping = false; 459 m_jumping = false;
342 Falling = false; 460 Falling = false;
343 actor.Selected = false; // borrowed for jumping flag 461 actor.Selected = false; // borrowed for jumping flag
344 m_jumpVelocity = 0f; 462 m_animTickLand = Environment.TickCount;
345 m_animTickFall = Environment.TickCount; 463 currentControlState = motionControlStates.landing;
346 return "LAND"; 464 return "LAND";
347 } 465 }
348 else if (jumptime > JUMP_PERIOD) 466 else if (jumptime > JUMP_PERIOD)
349 { 467 {
350 // jump down 468 // jump down
351 m_jumpVelocity = 0f;
352 return "JUMP"; 469 return "JUMP";
353 } 470 }
354 else if (jumptime > PREJUMP_DELAY) 471 else if (jumptime > PREJUMP_DELAY)
355 { 472 {
356 // jump up 473 // jump up
357 m_jumping = true; 474 m_jumping = true;
358 m_jumpVelocity = 10f;
359 return "JUMP"; 475 return "JUMP";
360 } 476 }
477 return CurrentMovementAnimation;
361 } 478 }
362 479
363 #endregion Jumping 480 #endregion Jumping
364 481
365 #region Ground Movement 482 #region Ground Movement
366 483
367 if (CurrentMovementAnimation == "FALLDOWN") 484 if (currentControlState == motionControlStates.falling)
368 { 485 {
369 Falling = false; 486 Falling = false;
370 m_animTickFall = Environment.TickCount; 487 currentControlState = motionControlStates.landing;
488 m_animTickLand = Environment.TickCount;
371 // TODO: SOFT_LAND support 489 // TODO: SOFT_LAND support
372 float fallHeight = m_fallHeight - actor.Position.Z; 490 float fallVsq = m_lastFallVelocity * m_lastFallVelocity;
373 if (fallHeight > 15.0f) 491 if (fallVsq > 300f) // aprox 20*h
374 return "STANDUP"; 492 return "STANDUP";
375 else if (fallHeight > 8.0f) 493 else if (fallVsq > 160f)
376 return "SOFT_LAND"; 494 return "SOFT_LAND";
377 else 495 else
378 return "LAND"; 496 return "LAND";
379 } 497 }
380 else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP")) 498
499
500 if (currentControlState == motionControlStates.landing)
381 { 501 {
382 int landElapsed = Environment.TickCount - m_animTickFall; 502 Falling = false;
503 int landElapsed = Environment.TickCount - m_animTickLand;
383 int limit = 1000; 504 int limit = 1000;
384 if (CurrentMovementAnimation == "LAND") 505 if (CurrentMovementAnimation == "LAND")
385 limit = 350; 506 limit = 350;
386 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client 507 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
387 508
388 if ((m_animTickFall != 0) && (landElapsed <= limit)) 509 if ((m_animTickLand != 0) && (landElapsed <= limit))
389 { 510 {
390 return CurrentMovementAnimation; 511 return CurrentMovementAnimation;
391 } 512 }
392 else 513 else
393 { 514 {
394 m_fallHeight = actor.Position.Z; // save latest flying height 515 currentControlState = motionControlStates.onsurface;
516 m_animTickLand = 0;
395 return "STAND"; 517 return "STAND";
396 } 518 }
397 } 519 }
398 520
399 // next section moved outside paren. and realigned for jumping 521 // next section moved outside paren. and realigned for jumping
400 if (move.X != 0f || move.Y != 0f) 522
523 if (heldOnXY)
401 { 524 {
402 m_fallHeight = actor.Position.Z; // save latest flying height 525 currentControlState = motionControlStates.onsurface;
403 Falling = false; 526 Falling = false;
404 // Walking / crouchwalking / running 527 // Walking / crouchwalking / running
405 if (move.Z < 0f) 528 if (heldDown)
406 { 529 {
407 return "CROUCHWALK"; 530 return "CROUCHWALK";
408 } 531 }
@@ -416,11 +539,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
416 return "WALK"; 539 return "WALK";
417 } 540 }
418 } 541 }
419 else if (!m_jumping) 542 else
420 { 543 {
544 currentControlState = motionControlStates.onsurface;
421 Falling = false; 545 Falling = false;
422 // Not walking 546 // Not walking
423 if (move.Z < 0) 547 if (heldDown)
424 return "CROUCH"; 548 return "CROUCH";
425 else if (heldTurnLeft) 549 else if (heldTurnLeft)
426 return "TURNLEFT"; 550 return "TURNLEFT";
@@ -431,8 +555,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
431 } 555 }
432 #endregion Ground Movement 556 #endregion Ground Movement
433 557
434 Falling = false;
435
436 return CurrentMovementAnimation; 558 return CurrentMovementAnimation;
437 } 559 }
438 560
@@ -442,7 +564,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
442 /// <returns>'true' if the animation was changed</returns> 564 /// <returns>'true' if the animation was changed</returns>
443 public bool UpdateMovementAnimations() 565 public bool UpdateMovementAnimations()
444 { 566 {
445// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name); 567 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name);
446 568
447 bool ret = false; 569 bool ret = false;
448 lock (m_animations) 570 lock (m_animations)
@@ -450,7 +572,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
450 string newMovementAnimation = DetermineMovementAnimation(); 572 string newMovementAnimation = DetermineMovementAnimation();
451 if (CurrentMovementAnimation != newMovementAnimation) 573 if (CurrentMovementAnimation != newMovementAnimation)
452 { 574 {
453 CurrentMovementAnimation = DetermineMovementAnimation(); 575 CurrentMovementAnimation = newMovementAnimation;
454 576
455// m_log.DebugFormat( 577// m_log.DebugFormat(
456// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", 578// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
@@ -464,6 +586,24 @@ namespace OpenSim.Region.Framework.Scenes.Animation
464 return ret; 586 return ret;
465 } 587 }
466 588
589 public bool ForceUpdateMovementAnimations()
590 {
591 lock (m_animations)
592 {
593 CurrentMovementAnimation = DetermineMovementAnimation();
594 return TrySetMovementAnimation(CurrentMovementAnimation);
595 }
596 }
597
598 public bool SetMovementAnimations(string motionState)
599 {
600 lock (m_animations)
601 {
602 CurrentMovementAnimation = motionState;
603 return TrySetMovementAnimation(CurrentMovementAnimation);
604 }
605 }
606
467 public UUID[] GetAnimationArray() 607 public UUID[] GetAnimationArray()
468 { 608 {
469 UUID[] animIDs; 609 UUID[] animIDs;
@@ -472,19 +612,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation
472 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 612 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
473 return animIDs; 613 return animIDs;
474 } 614 }
475 615
476 public BinBVHAnimation GenerateRandomAnimation() 616 public BinBVHAnimation GenerateRandomAnimation()
477 { 617 {
478 int rnditerations = 3; 618 int rnditerations = 3;
479 BinBVHAnimation anim = new BinBVHAnimation(); 619 BinBVHAnimation anim = new BinBVHAnimation();
480 List<string> parts = new List<string>(); 620 List<string> parts = new List<string>();
481 parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso"); 621 parts.Add("mPelvis"); parts.Add("mHead"); parts.Add("mTorso");
482 parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft"); 622 parts.Add("mHipLeft"); parts.Add("mHipRight"); parts.Add("mHipLeft"); parts.Add("mKneeLeft");
483 parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck"); 623 parts.Add("mKneeRight"); parts.Add("mCollarLeft"); parts.Add("mCollarRight"); parts.Add("mNeck");
484 parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight"); 624 parts.Add("mElbowLeft"); parts.Add("mElbowRight"); parts.Add("mWristLeft"); parts.Add("mWristRight");
485 parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight"); 625 parts.Add("mShoulderLeft"); parts.Add("mShoulderRight"); parts.Add("mAnkleLeft"); parts.Add("mAnkleRight");
486 parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight"); 626 parts.Add("mEyeRight"); parts.Add("mChest"); parts.Add("mToeLeft"); parts.Add("mToeRight");
487 parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft"); 627 parts.Add("mFootLeft"); parts.Add("mFootRight"); parts.Add("mEyeLeft");
488 anim.HandPose = 1; 628 anim.HandPose = 1;
489 anim.InPoint = 0; 629 anim.InPoint = 0;
490 anim.OutPoint = (rnditerations * .10f); 630 anim.OutPoint = (rnditerations * .10f);
@@ -508,12 +648,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
508 for (int i = 0; i < rnditerations; i++) 648 for (int i = 0; i < rnditerations; i++)
509 { 649 {
510 anim.Joints[j].rotationkeys[i] = new binBVHJointKey(); 650 anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
511 anim.Joints[j].rotationkeys[i].time = (i*.10f); 651 anim.Joints[j].rotationkeys[i].time = (i * .10f);
512 anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1); 652 anim.Joints[j].rotationkeys[i].key_element.X = ((float)rnd.NextDouble() * 2 - 1);
513 anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1); 653 anim.Joints[j].rotationkeys[i].key_element.Y = ((float)rnd.NextDouble() * 2 - 1);
514 anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1); 654 anim.Joints[j].rotationkeys[i].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
515 anim.Joints[j].positionkeys[i] = new binBVHJointKey(); 655 anim.Joints[j].positionkeys[i] = new binBVHJointKey();
516 anim.Joints[j].positionkeys[i].time = (i*.10f); 656 anim.Joints[j].positionkeys[i].time = (i * .10f);
517 anim.Joints[j].positionkeys[i].key_element.X = 0; 657 anim.Joints[j].positionkeys[i].key_element.X = 0;
518 anim.Joints[j].positionkeys[i].key_element.Y = 0; 658 anim.Joints[j].positionkeys[i].key_element.Y = 0;
519 anim.Joints[j].positionkeys[i].key_element.Z = 0; 659 anim.Joints[j].positionkeys[i].key_element.Z = 0;
@@ -540,20 +680,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
540 /// <param name="objectIDs"></param> 680 /// <param name="objectIDs"></param>
541 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) 681 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
542 { 682 {
543 if (m_scenePresence.IsChildAgent) 683 m_scenePresence.SendAnimPack(animations, seqs, objectIDs);
544 return; 684 }
545 685
546// m_log.DebugFormat( 686 public void GetArrays(out UUID[] animIDs, out int[] sequenceNums, out UUID[] objectIDs)
547// "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'", 687 {
548// string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())), 688 animIDs = null;
549// string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())), 689 sequenceNums = null;
550// string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString()))); 690 objectIDs = null;
551 691
552 m_scenePresence.Scene.ForEachClient( 692 if (m_animations != null)
553 delegate(IClientAPI client) 693 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
554 {
555 client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
556 });
557 } 694 }
558 695
559 public void SendAnimPackToClient(IClientAPI client) 696 public void SendAnimPackToClient(IClientAPI client)
@@ -575,7 +712,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
575 public void SendAnimPack() 712 public void SendAnimPack()
576 { 713 {
577 //m_log.Debug("Sending animation pack to all"); 714 //m_log.Debug("Sending animation pack to all");
578 715
579 if (m_scenePresence.IsChildAgent) 716 if (m_scenePresence.IsChildAgent)
580 return; 717 return;
581 718
@@ -585,7 +722,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
585 722
586 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 723 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
587 724
588 SendAnimPack(animIDs, sequenceNums, objectIDs); 725 // SendAnimPack(animIDs, sequenceNums, objectIDs);
726 m_scenePresence.SendAnimPack(animIDs, sequenceNums, objectIDs);
589 } 727 }
590 728
591 public string GetAnimName(UUID animId) 729 public string GetAnimName(UUID animId)
diff --git a/OpenSim/Region/Framework/Scenes/CollisionSounds.cs b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
new file mode 100644
index 0000000..075724e
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
@@ -0,0 +1,304 @@
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// Ubit 2012
28
29using System;
30using System.Reflection;
31using System.Collections.Generic;
32using OpenMetaverse;
33using OpenSim.Framework;
34using log4net;
35
36namespace OpenSim.Region.Framework.Scenes
37{
38 public struct CollisionForSoundInfo
39 {
40 public uint colliderID;
41 public Vector3 position;
42 public float relativeVel;
43 }
44
45 public static class CollisionSounds
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private const int MaxMaterials = 7;
50 // part part
51
52 private static UUID snd_StoneStone = new UUID("be7295c0-a158-11e1-b3dd-0800200c9a66");
53 private static UUID snd_StoneMetal = new UUID("be7295c0-a158-11e1-b3dd-0800201c9a66");
54 private static UUID snd_StoneGlass = new UUID("be7295c0-a158-11e1-b3dd-0800202c9a66");
55 private static UUID snd_StoneWood = new UUID("be7295c0-a158-11e1-b3dd-0800203c9a66");
56 private static UUID snd_StoneFlesh = new UUID("be7295c0-a158-11e1-b3dd-0800204c9a66");
57 private static UUID snd_StonePlastic = new UUID("be7295c0-a158-11e1-b3dd-0800205c9a66");
58 private static UUID snd_StoneRubber = new UUID("be7295c0-a158-11e1-b3dd-0800206c9a66");
59
60 private static UUID snd_MetalMetal = new UUID("be7295c0-a158-11e1-b3dd-0801201c9a66");
61 private static UUID snd_MetalGlass = new UUID("be7295c0-a158-11e1-b3dd-0801202c9a66");
62 private static UUID snd_MetalWood = new UUID("be7295c0-a158-11e1-b3dd-0801203c9a66");
63 private static UUID snd_MetalFlesh = new UUID("be7295c0-a158-11e1-b3dd-0801204c9a66");
64 private static UUID snd_MetalPlastic = new UUID("be7295c0-a158-11e1-b3dd-0801205c9a66");
65 private static UUID snd_MetalRubber = new UUID("be7295c0-a158-11e1-b3dd-0801206c9a66");
66
67 private static UUID snd_GlassGlass = new UUID("be7295c0-a158-11e1-b3dd-0802202c9a66");
68 private static UUID snd_GlassWood = new UUID("be7295c0-a158-11e1-b3dd-0802203c9a66");
69 private static UUID snd_GlassFlesh = new UUID("be7295c0-a158-11e1-b3dd-0802204c9a66");
70 private static UUID snd_GlassPlastic = new UUID("be7295c0-a158-11e1-b3dd-0802205c9a66");
71 private static UUID snd_GlassRubber = new UUID("be7295c0-a158-11e1-b3dd-0802206c9a66");
72
73 private static UUID snd_WoodWood = new UUID("be7295c0-a158-11e1-b3dd-0803203c9a66");
74 private static UUID snd_WoodFlesh = new UUID("be7295c0-a158-11e1-b3dd-0803204c9a66");
75 private static UUID snd_WoodPlastic = new UUID("be7295c0-a158-11e1-b3dd-0803205c9a66");
76 private static UUID snd_WoodRubber = new UUID("be7295c0-a158-11e1-b3dd-0803206c9a66");
77
78 private static UUID snd_FleshFlesh = new UUID("be7295c0-a158-11e1-b3dd-0804204c9a66");
79 private static UUID snd_FleshPlastic = new UUID("be7295c0-a158-11e1-b3dd-0804205c9a66");
80 private static UUID snd_FleshRubber = new UUID("be7295c0-a158-11e1-b3dd-0804206c9a66");
81
82 private static UUID snd_PlasticPlastic = new UUID("be7295c0-a158-11e1-b3dd-0805205c9a66");
83 private static UUID snd_PlasticRubber = new UUID("be7295c0-a158-11e1-b3dd-0805206c9a66");
84
85 private static UUID snd_RubberRubber = new UUID("be7295c0-a158-11e1-b3dd-0806206c9a66");
86
87 // terrain part
88 private static UUID snd_TerrainStone = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
89 private static UUID snd_TerrainMetal = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
90 private static UUID snd_TerrainGlass = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
91 private static UUID snd_TerrainWood = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
92 private static UUID snd_TerrainFlesh = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
93 private static UUID snd_TerrainPlastic = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
94 private static UUID snd_TerrainRubber = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
95
96 public static UUID[] m_TerrainPart = {
97 snd_TerrainStone,
98 snd_TerrainMetal,
99 snd_TerrainGlass,
100 snd_TerrainWood,
101 snd_TerrainFlesh,
102 snd_TerrainPlastic,
103 snd_TerrainRubber
104 };
105
106 // simetric sounds
107 public static UUID[] m_PartPart = {
108 snd_StoneStone, snd_StoneMetal, snd_StoneGlass, snd_StoneWood, snd_StoneFlesh, snd_StonePlastic, snd_StoneRubber,
109 snd_StoneMetal, snd_MetalMetal, snd_MetalGlass, snd_MetalWood, snd_MetalFlesh, snd_MetalPlastic, snd_MetalRubber,
110 snd_StoneGlass, snd_MetalGlass, snd_GlassGlass, snd_GlassWood, snd_GlassFlesh, snd_GlassPlastic, snd_GlassRubber,
111 snd_StoneWood, snd_MetalWood, snd_GlassWood, snd_WoodWood, snd_WoodFlesh, snd_WoodPlastic, snd_WoodRubber,
112 snd_StoneFlesh, snd_MetalFlesh, snd_GlassFlesh, snd_WoodFlesh, snd_FleshFlesh, snd_FleshPlastic, snd_FleshRubber,
113 snd_StonePlastic, snd_MetalPlastic, snd_GlassPlastic, snd_WoodPlastic, snd_FleshPlastic, snd_PlasticPlastic, snd_PlasticRubber,
114 snd_StoneRubber, snd_MetalRubber, snd_GlassRubber, snd_WoodRubber, snd_FleshRubber, snd_PlasticRubber, snd_RubberRubber
115 };
116
117 public static void PartCollisionSound(SceneObjectPart part, List<CollisionForSoundInfo> collidersinfolist)
118 {
119 if (collidersinfolist.Count == 0 || part == null)
120 return;
121
122 if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0)
123 return;
124
125 if (part.ParentGroup == null)
126 return;
127
128 if (part.CollisionSoundType < 0)
129 return;
130
131 float volume = 0.0f;
132 bool HaveSound = false;
133
134 UUID soundID = part.CollisionSound;
135
136 if (part.CollisionSoundType > 0)
137 {
138 // soundID = part.CollisionSound;
139 volume = part.CollisionSoundVolume;
140 if (volume == 0.0f)
141 return;
142 HaveSound = true;
143 }
144
145 bool doneownsound = false;
146
147 int thisMaterial = (int)part.Material;
148 if (thisMaterial >= MaxMaterials)
149 thisMaterial = 3;
150 int thisMatScaled = thisMaterial * MaxMaterials;
151
152 CollisionForSoundInfo colInfo;
153 uint id;
154
155 for(int i = 0; i< collidersinfolist.Count; i++)
156 {
157 colInfo = collidersinfolist[i];
158
159 id = colInfo.colliderID;
160 if (id == 0) // terrain collision
161 {
162 if (!doneownsound)
163 {
164 if (!HaveSound)
165 {
166 volume = Math.Abs(colInfo.relativeVel);
167 if (volume < 0.2f)
168 continue;
169
170 volume *= volume * .0625f; // 4m/s == full volume
171 if (volume > 1.0f)
172 volume = 1.0f;
173
174 soundID = m_TerrainPart[thisMaterial];
175 }
176 part.SendCollisionSound(soundID, volume, colInfo.position);
177 doneownsound = true;
178 }
179 continue;
180 }
181
182 SceneObjectPart otherPart = part.ParentGroup.Scene.GetSceneObjectPart(id);
183 if (otherPart != null)
184 {
185 if (otherPart.CollisionSoundType < 0 || otherPart.VolumeDetectActive)
186 continue;
187
188 if (!HaveSound)
189 {
190 if (otherPart.CollisionSoundType > 0)
191 {
192 soundID = otherPart.CollisionSound;
193 volume = otherPart.CollisionSoundVolume;
194 if (volume == 0.0f)
195 continue;
196 }
197 else
198 {
199 volume = Math.Abs(colInfo.relativeVel);
200 if (volume < 0.2f)
201 continue;
202
203 volume *= volume * .0625f; // 4m/s == full volume
204 if (volume > 1.0f)
205 volume = 1.0f;
206
207 int otherMaterial = (int)otherPart.Material;
208 if (otherMaterial >= MaxMaterials)
209 otherMaterial = 3;
210
211 soundID = m_PartPart[thisMatScaled + otherMaterial];
212 }
213 }
214
215 if (doneownsound)
216 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
217 else
218 {
219 part.SendCollisionSound(soundID, volume, colInfo.position);
220 doneownsound = true;
221 }
222 }
223 }
224 }
225
226 public static void AvatarCollisionSound(ScenePresence av, List<CollisionForSoundInfo> collidersinfolist)
227 {
228 if (collidersinfolist.Count == 0 || av == null)
229 return;
230
231 UUID soundID;
232 int otherMaterial;
233
234 int thisMaterial = 4; // flesh
235
236 int thisMatScaled = thisMaterial * MaxMaterials;
237
238 // bool doneownsound = false;
239
240 CollisionForSoundInfo colInfo;
241 uint id;
242 float volume;
243
244 for(int i = 0; i< collidersinfolist.Count; i++)
245 {
246 colInfo = collidersinfolist[i];
247
248 id = colInfo.colliderID;
249
250 if (id == 0) // no terrain collision sounds for now
251 {
252 continue;
253// volume = Math.Abs(colInfo.relativeVel);
254// if (volume < 0.2f)
255// continue;
256
257 }
258
259 SceneObjectPart otherPart = av.Scene.GetSceneObjectPart(id);
260 if (otherPart != null)
261 {
262 if (otherPart.CollisionSoundType < 0)
263 continue;
264 if (otherPart.CollisionSoundType > 0 && otherPart.CollisionSoundVolume > 0f)
265 otherPart.SendCollisionSound(otherPart.CollisionSound, otherPart.CollisionSoundVolume, colInfo.position);
266 else
267 {
268 volume = Math.Abs(colInfo.relativeVel);
269 // Most noral collisions (running into walls, stairs)
270 // should never be heard.
271 if (volume < 3.2f)
272 continue;
273// m_log.DebugFormat("Collision speed was {0}", volume);
274
275 // Cap to 0.2 times volume because climbing stairs should not be noisy
276 // Also changed scaling
277 volume *= volume * .0125f; // 4m/s == volume 0.2
278 if (volume > 0.2f)
279 volume = 0.2f;
280 otherMaterial = (int)otherPart.Material;
281 if (otherMaterial >= MaxMaterials)
282 otherMaterial = 3;
283
284 soundID = m_PartPart[thisMatScaled + otherMaterial];
285 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
286 }
287 continue;
288 }
289/*
290 else if (!doneownsound)
291 {
292 ScenePresence otherav = av.Scene.GetScenePresence(Id);
293 if (otherav != null && (!otherav.IsChildAgent))
294 {
295 soundID = snd_FleshFlesh;
296 av.SendCollisionSound(soundID, 1.0);
297 doneownsound = true;
298 }
299 }
300 */
301 }
302 }
303 }
304}
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 97b9482..0a6bca4 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -80,6 +80,7 @@ namespace OpenSim.Region.Framework.Scenes
80 public event OnTerrainTaintedDelegate OnTerrainTainted; 80 public event OnTerrainTaintedDelegate OnTerrainTainted;
81 81
82 public delegate void OnTerrainTickDelegate(); 82 public delegate void OnTerrainTickDelegate();
83 public delegate void OnTerrainCheckUpdatesDelegate();
83 84
84 /// <summary> 85 /// <summary>
85 /// Triggered if the terrain has been edited 86 /// Triggered if the terrain has been edited
@@ -89,6 +90,11 @@ namespace OpenSim.Region.Framework.Scenes
89 /// but is used by core solely to update the physics engine. 90 /// but is used by core solely to update the physics engine.
90 /// </remarks> 91 /// </remarks>
91 public event OnTerrainTickDelegate OnTerrainTick; 92 public event OnTerrainTickDelegate OnTerrainTick;
93 public event OnTerrainCheckUpdatesDelegate OnTerrainCheckUpdates;
94
95 public delegate void OnTerrainUpdateDelegate();
96
97 public event OnTerrainUpdateDelegate OnTerrainUpdate;
92 98
93 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 99 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
94 100
@@ -339,8 +345,6 @@ namespace OpenSim.Region.Framework.Scenes
339 /// in <see cref="Scene.SetScriptRunning"/> 345 /// in <see cref="Scene.SetScriptRunning"/>
340 /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>, 346 /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>,
341 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/> 347 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/>
342 /// XXX: This is only triggered when it is the client that starts the script, not in other situations where
343 /// a script is started, unlike OnStopScript!
344 /// </remarks> 348 /// </remarks>
345 public event StartScript OnStartScript; 349 public event StartScript OnStartScript;
346 350
@@ -354,7 +358,6 @@ namespace OpenSim.Region.Framework.Scenes
354 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>, 358 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>,
355 /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>, 359 /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>,
356 /// <see cref="Scene.SetScriptRunning"/> 360 /// <see cref="Scene.SetScriptRunning"/>
357 /// XXX: This is triggered when a sciprt is stopped for any reason, unlike OnStartScript!
358 /// </remarks> 361 /// </remarks>
359 public event StopScript OnStopScript; 362 public event StopScript OnStopScript;
360 363
@@ -858,6 +861,10 @@ namespace OpenSim.Region.Framework.Scenes
858 public event ParcelPrimCountTainted OnParcelPrimCountTainted; 861 public event ParcelPrimCountTainted OnParcelPrimCountTainted;
859 public event GetScriptRunning OnGetScriptRunning; 862 public event GetScriptRunning OnGetScriptRunning;
860 863
864 public delegate void ThrottleUpdate(ScenePresence scenePresence);
865
866 public event ThrottleUpdate OnThrottleUpdate;
867
861 /// <summary> 868 /// <summary>
862 /// RegisterCapsEvent is called by Scene after the Caps object 869 /// RegisterCapsEvent is called by Scene after the Caps object
863 /// has been instantiated and before it is return to the 870 /// has been instantiated and before it is return to the
@@ -1377,7 +1384,9 @@ namespace OpenSim.Region.Framework.Scenes
1377 { 1384 {
1378 try 1385 try
1379 { 1386 {
1387// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate: {0}",d.Target.ToString());
1380 d(agentId); 1388 d(agentId);
1389// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate done ");
1381 } 1390 }
1382 catch (Exception e) 1391 catch (Exception e)
1383 { 1392 {
@@ -1451,6 +1460,26 @@ namespace OpenSim.Region.Framework.Scenes
1451 } 1460 }
1452 } 1461 }
1453 } 1462 }
1463 public void TriggerTerrainUpdate()
1464 {
1465 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
1466 if (handlerTerrainUpdate != null)
1467 {
1468 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
1469 {
1470 try
1471 {
1472 d();
1473 }
1474 catch (Exception e)
1475 {
1476 m_log.ErrorFormat(
1477 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
1478 e.Message, e.StackTrace);
1479 }
1480 }
1481 }
1482 }
1454 1483
1455 public void TriggerTerrainTick() 1484 public void TriggerTerrainTick()
1456 { 1485 {
@@ -1473,6 +1502,27 @@ namespace OpenSim.Region.Framework.Scenes
1473 } 1502 }
1474 } 1503 }
1475 1504
1505 public void TriggerTerrainCheckUpdates()
1506 {
1507 OnTerrainCheckUpdatesDelegate TerrainCheckUpdates = OnTerrainCheckUpdates;
1508 if (TerrainCheckUpdates != null)
1509 {
1510 foreach (OnTerrainCheckUpdatesDelegate d in TerrainCheckUpdates.GetInvocationList())
1511 {
1512 try
1513 {
1514 d();
1515 }
1516 catch (Exception e)
1517 {
1518 m_log.ErrorFormat(
1519 "[EVENT MANAGER]: Delegate for TerrainCheckUpdates failed - continuing. {0} {1}",
1520 e.Message, e.StackTrace);
1521 }
1522 }
1523 }
1524 }
1525
1476 public void TriggerTerrainTainted() 1526 public void TriggerTerrainTainted()
1477 { 1527 {
1478 OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted; 1528 OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted;
@@ -1808,6 +1858,7 @@ namespace OpenSim.Region.Framework.Scenes
1808 m_log.ErrorFormat( 1858 m_log.ErrorFormat(
1809 "[EVENT MANAGER]: Delegate for TriggerRemoveScript failed - continuing. {0} {1}", 1859 "[EVENT MANAGER]: Delegate for TriggerRemoveScript failed - continuing. {0} {1}",
1810 e.Message, e.StackTrace); 1860 e.Message, e.StackTrace);
1861 m_log.ErrorFormat(Environment.StackTrace);
1811 } 1862 }
1812 } 1863 }
1813 } 1864 }
@@ -2073,7 +2124,10 @@ namespace OpenSim.Region.Framework.Scenes
2073 { 2124 {
2074 try 2125 try
2075 { 2126 {
2127// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed: {0}", d.Target.ToString());
2076 d(ClientID, scene); 2128 d(ClientID, scene);
2129// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed done ");
2130
2077 } 2131 }
2078 catch (Exception e) 2132 catch (Exception e)
2079 { 2133 {
@@ -3107,6 +3161,7 @@ namespace OpenSim.Region.Framework.Scenes
3107 { 3161 {
3108 foreach (Action<Scene> d in handler.GetInvocationList()) 3162 foreach (Action<Scene> d in handler.GetInvocationList())
3109 { 3163 {
3164 m_log.InfoFormat("[EVENT MANAGER]: TriggerSceneShuttingDown invoque {0}", d.Method.Name.ToString());
3110 try 3165 try
3111 { 3166 {
3112 d(s); 3167 d(s);
@@ -3119,6 +3174,7 @@ namespace OpenSim.Region.Framework.Scenes
3119 } 3174 }
3120 } 3175 }
3121 } 3176 }
3177 m_log.Info("[EVENT MANAGER]: TriggerSceneShuttingDown done");
3122 } 3178 }
3123 3179
3124 public void TriggerOnRegionStarted(Scene scene) 3180 public void TriggerOnRegionStarted(Scene scene)
@@ -3310,6 +3366,15 @@ namespace OpenSim.Region.Framework.Scenes
3310 } 3366 }
3311 } 3367 }
3312 3368
3369 public void TriggerThrottleUpdate(ScenePresence scenePresence)
3370 {
3371 ThrottleUpdate handler = OnThrottleUpdate;
3372 if (handler != null)
3373 {
3374 handler(scenePresence);
3375 }
3376 }
3377
3313// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids) 3378// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3314// { 3379// {
3315// GatherUuids handler = OnGatherUuids; 3380// GatherUuids handler = OnGatherUuids;
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index bbf3b51..cdd8d2d 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -292,14 +292,17 @@ namespace OpenSim.Region.Framework.Scenes
292 292
293 private void StartTimer() 293 private void StartTimer()
294 { 294 {
295 KeyframeTimer.Add(this); 295 lock (m_frames)
296 m_timerStopped = false; 296 {
297 KeyframeTimer.Add(this);
298 m_timerStopped = false;
299 }
297 } 300 }
298 301
299 private void StopTimer() 302 private void StopTimer()
300 { 303 {
301 m_timerStopped = true; 304 lock (m_frames)
302 KeyframeTimer.Remove(this); 305 m_timerStopped = true;
303 } 306 }
304 307
305 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 308 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
@@ -348,24 +351,26 @@ namespace OpenSim.Region.Framework.Scenes
348 m_group = grp; 351 m_group = grp;
349 m_scene = grp.Scene; 352 m_scene = grp.Scene;
350 353
351 Vector3 grppos = grp.AbsolutePosition;
352 Vector3 offset = grppos - m_serializedPosition;
353 // avoid doing it more than once
354 // current this will happen dragging a prim to other region
355 m_serializedPosition = grppos;
356 354
357 m_basePosition += offset; 355 lock (m_frames)
358 m_nextPosition += offset;
359
360 m_currentFrame.StartPosition += offset;
361 m_currentFrame.Position += offset;
362
363 for (int i = 0; i < m_frames.Count; i++)
364 { 356 {
365 Keyframe k = m_frames[i]; 357 Vector3 grppos = grp.AbsolutePosition;
366 k.StartPosition += offset; 358 Vector3 offset = grppos - m_serializedPosition;
367 k.Position += offset; 359 // avoid doing it more than once
368 m_frames[i]=k; 360 // current this will happen draging a prim to other region
361 m_serializedPosition = grppos;
362
363 m_basePosition += offset;
364 m_currentFrame.Position += offset;
365
366 m_nextPosition += offset;
367
368 for (int i = 0; i < m_frames.Count; i++)
369 {
370 Keyframe k = m_frames[i];
371 k.Position += offset;
372 m_frames[i] = k;
373 }
369 } 374 }
370 375
371 if (m_running) 376 if (m_running)
@@ -410,25 +415,28 @@ namespace OpenSim.Region.Framework.Scenes
410 m_keyframes.CopyTo(newmotion.m_keyframes, 0); 415 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
411 } 416 }
412 417
413 newmotion.m_frames = new List<Keyframe>(m_frames); 418 lock (m_frames)
419 {
420 newmotion.m_frames = new List<Keyframe>(m_frames);
414 421
415 newmotion.m_basePosition = m_basePosition; 422 newmotion.m_basePosition = m_basePosition;
416 newmotion.m_baseRotation = m_baseRotation; 423 newmotion.m_baseRotation = m_baseRotation;
417 424
418 if (m_selected) 425 if (m_selected)
419 newmotion.m_serializedPosition = m_serializedPosition;
420 else
421 {
422 if (m_group != null)
423 newmotion.m_serializedPosition = m_group.AbsolutePosition;
424 else
425 newmotion.m_serializedPosition = m_serializedPosition; 426 newmotion.m_serializedPosition = m_serializedPosition;
426 } 427 else
428 {
429 if (m_group != null)
430 newmotion.m_serializedPosition = m_group.AbsolutePosition;
431 else
432 newmotion.m_serializedPosition = m_serializedPosition;
433 }
427 434
428 newmotion.m_currentFrame = m_currentFrame; 435 newmotion.m_currentFrame = m_currentFrame;
429 436
430 newmotion.m_iterations = m_iterations; 437 newmotion.m_iterations = m_iterations;
431 newmotion.m_running = m_running; 438 newmotion.m_running = m_running;
439 }
432 440
433 if (m_running && !m_waitingCrossing) 441 if (m_running && !m_waitingCrossing)
434 StartTimer(); 442 StartTimer();
@@ -458,19 +466,18 @@ namespace OpenSim.Region.Framework.Scenes
458 } 466 }
459 else 467 else
460 { 468 {
461 m_running = false;
462 StopTimer(); 469 StopTimer();
470 m_running = false;
463 } 471 }
464 } 472 }
465 473
466 public void Stop() 474 public void Stop()
467 { 475 {
476 StopTimer();
468 m_running = false; 477 m_running = false;
469 m_isCrossing = false; 478 m_isCrossing = false;
470 m_waitingCrossing = false; 479 m_waitingCrossing = false;
471 480
472 StopTimer();
473
474 m_basePosition = m_group.AbsolutePosition; 481 m_basePosition = m_group.AbsolutePosition;
475 m_baseRotation = m_group.GroupRotation; 482 m_baseRotation = m_group.GroupRotation;
476 483
@@ -483,14 +490,34 @@ namespace OpenSim.Region.Framework.Scenes
483 490
484 public void Pause() 491 public void Pause()
485 { 492 {
486 m_running = false;
487 StopTimer(); 493 StopTimer();
494 m_running = false;
488 495
489 m_group.RootPart.Velocity = Vector3.Zero; 496 m_group.RootPart.Velocity = Vector3.Zero;
490 m_group.RootPart.AngularVelocity = Vector3.Zero; 497 m_group.RootPart.AngularVelocity = Vector3.Zero;
491 m_group.SendGroupRootTerseUpdate(); 498 m_group.SendGroupRootTerseUpdate();
492// m_group.RootPart.ScheduleTerseUpdate(); 499// m_group.RootPart.ScheduleTerseUpdate();
500 }
493 501
502 public void Suspend()
503 {
504 lock (m_frames)
505 {
506 if (m_timerStopped)
507 return;
508 m_timerStopped = true;
509 }
510 }
511
512 public void Resume()
513 {
514 lock (m_frames)
515 {
516 if (!m_timerStopped)
517 return;
518 if (m_running && !m_waitingCrossing)
519 StartTimer();
520 }
494 } 521 }
495 522
496 private void GetNextList() 523 private void GetNextList()
@@ -581,6 +608,7 @@ namespace OpenSim.Region.Framework.Scenes
581 608
582 pos = (Vector3)k.Position; 609 pos = (Vector3)k.Position;
583 rot = (Quaternion)k.Rotation; 610 rot = (Quaternion)k.Rotation;
611
584 } 612 }
585 613
586 m_basePosition = pos; 614 m_basePosition = pos;
@@ -592,15 +620,41 @@ namespace OpenSim.Region.Framework.Scenes
592 620
593 public void OnTimer(double tickDuration) 621 public void OnTimer(double tickDuration)
594 { 622 {
623 if (!Monitor.TryEnter(m_frames))
624 return;
625 if (m_timerStopped)
626 KeyframeTimer.Remove(this);
627 else
628 DoOnTimer(tickDuration);
629 Monitor.Exit(m_frames);
630 }
631
632 private void Done()
633 {
634 KeyframeTimer.Remove(this);
635 m_timerStopped = true;
636 m_running = false;
637 m_isCrossing = false;
638 m_waitingCrossing = false;
639
640 m_basePosition = m_group.AbsolutePosition;
641 m_baseRotation = m_group.GroupRotation;
642
643 m_group.RootPart.Velocity = Vector3.Zero;
644 m_group.RootPart.AngularVelocity = Vector3.Zero;
645 m_group.SendGroupRootTerseUpdate();
646 // m_group.RootPart.ScheduleTerseUpdate();
647 m_frames.Clear();
648 }
649
650 private void DoOnTimer(double tickDuration)
651 {
595 if (m_skipLoops > 0) 652 if (m_skipLoops > 0)
596 { 653 {
597 m_skipLoops--; 654 m_skipLoops--;
598 return; 655 return;
599 } 656 }
600 657
601 if (m_timerStopped) // trap events still in air even after a timer.stop
602 return;
603
604 if (m_group == null) 658 if (m_group == null)
605 return; 659 return;
606 660
@@ -612,7 +666,6 @@ namespace OpenSim.Region.Framework.Scenes
612 { 666 {
613 m_group.RootPart.Velocity = Vector3.Zero; 667 m_group.RootPart.Velocity = Vector3.Zero;
614 m_group.SendGroupRootTerseUpdate(); 668 m_group.SendGroupRootTerseUpdate();
615
616 } 669 }
617 return; 670 return;
618 } 671 }
@@ -635,32 +688,22 @@ namespace OpenSim.Region.Framework.Scenes
635 688
636 if (m_frames.Count == 0) 689 if (m_frames.Count == 0)
637 { 690 {
638 if (!m_running) return; 691 lock (m_frames)
639
640 GetNextList();
641
642 if (m_frames.Count == 0)
643 { 692 {
644 Stop(); 693 GetNextList();
645// Scene scene = m_group.Scene;
646//
647// IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
648// foreach (IScriptModule m in scriptModules)
649// {
650// if (m == null)
651// continue;
652// m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
653// }
654
655 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
656
657 return;
658 }
659 694
660 m_currentFrame = m_frames[0]; 695 if (m_frames.Count == 0)
661 m_currentFrame.TimeMS += (int)tickDuration; 696 {
697 Done();
698 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
699 return;
700 }
662 701
702 m_currentFrame = m_frames[0];
703 m_currentFrame.TimeMS += (int)tickDuration;
704 }
663 //force a update on a keyframe transition 705 //force a update on a keyframe transition
706 m_nextPosition = m_group.AbsolutePosition;
664 update = true; 707 update = true;
665 } 708 }
666 709
@@ -681,9 +724,13 @@ namespace OpenSim.Region.Framework.Scenes
681 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); 724 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
682 725
683 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; 726 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
684 m_frames.RemoveAt(0); 727
685 if (m_frames.Count > 0) 728 lock (m_frames)
686 m_currentFrame = m_frames[0]; 729 {
730 m_frames.RemoveAt(0);
731 if (m_frames.Count > 0)
732 m_currentFrame = m_frames[0];
733 }
687 734
688 update = true; 735 update = true;
689 } 736 }
@@ -692,17 +739,14 @@ namespace OpenSim.Region.Framework.Scenes
692 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; 739 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
693 bool lastStep = m_currentFrame.TimeMS <= tickDuration; 740 bool lastStep = m_currentFrame.TimeMS <= tickDuration;
694 741
695 Vector3 positionThisStep = m_currentFrame.StartPosition + (m_currentFrame.Position.Value - m_currentFrame.StartPosition) * completed; 742 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
696 Vector3 motionThisStep = positionThisStep - m_group.AbsolutePosition; 743 Vector3 motionThisFrame = v / (float)remainingSteps;
744 v = v * 1000 / m_currentFrame.TimeMS;
697 745
698 float mag = Vector3.Mag(motionThisStep); 746 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
699 747
700 if ((mag >= 0.02f) || lastStep) 748 if (Vector3.Mag(motionThisFrame) >= 0.05f)
701 {
702 m_nextPosition = m_group.AbsolutePosition + motionThisStep;
703 m_group.AbsolutePosition = m_nextPosition;
704 update = true; 749 update = true;
705 }
706 750
707 //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration; 751 //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration;
708 //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})", 752 //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})",
@@ -714,43 +758,41 @@ namespace OpenSim.Region.Framework.Scenes
714 758
715 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); 759 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed);
716 step.Normalize(); 760 step.Normalize();
717/* use simpler change detection 761 /* use simpler change detection
718* float angle = 0; 762 * float angle = 0;
719 763
720 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 764 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
721 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 765 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
722 float aa_bb = aa * bb; 766 float aa_bb = aa * bb;
723 767
724 if (aa_bb == 0) 768 if (aa_bb == 0)
725 { 769 {
726 angle = 0; 770 angle = 0;
727 } 771 }
728 else 772 else
729 { 773 {
730 float ab = current.X * step.X + 774 float ab = current.X * step.X +
731 current.Y * step.Y + 775 current.Y * step.Y +
732 current.Z * step.Z + 776 current.Z * step.Z +
733 current.W * step.W; 777 current.W * step.W;
734 float q = (ab * ab) / aa_bb; 778 float q = (ab * ab) / aa_bb;
735 779
736 if (q > 1.0f) 780 if (q > 1.0f)
737 { 781 {
738 angle = 0; 782 angle = 0;
739 } 783 }
740 else 784 else
741 { 785 {
742 angle = (float)Math.Acos(2 * q - 1); 786 angle = (float)Math.Acos(2 * q - 1);
743 } 787 }
744 } 788 }
745 789
746 if (angle > 0.01f) 790 if (angle > 0.01f)
747*/ 791 */
748 if(Math.Abs(step.X - current.X) > 0.001f 792 if (Math.Abs(step.X - current.X) > 0.001f
749 || Math.Abs(step.Y - current.Y) > 0.001f 793 || Math.Abs(step.Y - current.Y) > 0.001f
750 || Math.Abs(step.Z - current.Z) > 0.001f 794 || Math.Abs(step.Z - current.Z) > 0.001f)
751 || lastStep) 795 // assuming w is a dependente var
752 // assuming w is a dependente var
753
754 { 796 {
755// m_group.UpdateGroupRotationR(step); 797// m_group.UpdateGroupRotationR(step);
756 m_group.RootPart.RotationOffset = step; 798 m_group.RootPart.RotationOffset = step;
@@ -763,25 +805,31 @@ namespace OpenSim.Region.Framework.Scenes
763 805
764 if (update) 806 if (update)
765 { 807 {
808 m_group.AbsolutePosition = m_nextPosition;
766 m_group.SendGroupRootTerseUpdate(); 809 m_group.SendGroupRootTerseUpdate();
767 } 810 }
768 } 811 }
769 812
770 public Byte[] Serialize() 813 public Byte[] Serialize()
771 { 814 {
815 bool timerWasStopped;
816 lock (m_frames)
817 {
818 timerWasStopped = m_timerStopped;
819 }
772 StopTimer(); 820 StopTimer();
773 821
774 SceneObjectGroup tmp = m_group; 822 SceneObjectGroup tmp = m_group;
775 m_group = null; 823 m_group = null;
776 if (!m_selected && tmp != null) 824
777 m_serializedPosition = tmp.AbsolutePosition;
778
779 using (MemoryStream ms = new MemoryStream()) 825 using (MemoryStream ms = new MemoryStream())
780 { 826 {
781 BinaryFormatter fmt = new BinaryFormatter(); 827 BinaryFormatter fmt = new BinaryFormatter();
828 if (!m_selected && tmp != null)
829 m_serializedPosition = tmp.AbsolutePosition;
782 fmt.Serialize(ms, this); 830 fmt.Serialize(ms, this);
783 m_group = tmp; 831 m_group = tmp;
784 if (m_running && !m_waitingCrossing) 832 if (!timerWasStopped && m_running && !m_waitingCrossing)
785 StartTimer(); 833 StartTimer();
786 834
787 return ms.ToArray(); 835 return ms.ToArray();
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index ae85560..bd9d580 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -91,6 +91,11 @@ namespace OpenSim.Region.Framework.Scenes
91 return 0; 91 return 0;
92 92
93 uint priority; 93 uint priority;
94
95
96 // HACK
97 return GetPriorityByBestAvatarResponsiveness(client, entity);
98
94 99
95 switch (m_scene.UpdatePrioritizationScheme) 100 switch (m_scene.UpdatePrioritizationScheme)
96 { 101 {
@@ -157,30 +162,31 @@ namespace OpenSim.Region.Framework.Scenes
157 162
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 163 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 164 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 165 uint pqueue = 2; // keep compiler happy
161 166
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 167 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 168 if (presence != null)
164 { 169 {
165 if (!presence.IsChildAgent) 170 // All avatars other than our own go into pqueue 1
171 if (entity is ScenePresence)
172 return 1;
173
174 if (entity is SceneObjectPart)
166 { 175 {
167 // All avatars other than our own go into pqueue 1 176 // Attachments are high priority,
168 if (entity is ScenePresence) 177 if (((SceneObjectPart)entity).ParentGroup.IsAttachment)
169 return 1; 178 return 2;
170 179
171 if (entity is SceneObjectPart) 180 pqueue = ComputeDistancePriority(client, entity, false);
172 { 181
173 // Attachments are high priority, 182 // Non physical prims are lower priority than physical prims
174 if (((SceneObjectPart)entity).ParentGroup.IsAttachment) 183 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
175 return 1; 184 if (physActor == null || !physActor.IsPhysical)
176 185 pqueue++;
177 // Non physical prims are lower priority than physical prims
178 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
179 if (physActor == null || !physActor.IsPhysical)
180 pqueue++;
181 }
182 } 186 }
183 } 187 }
188 else
189 pqueue = ComputeDistancePriority(client, entity, false);
184 190
185 return pqueue; 191 return pqueue;
186 } 192 }
@@ -212,25 +218,43 @@ namespace OpenSim.Region.Framework.Scenes
212 } 218 }
213 219
214 // Use the camera position for local agents and avatar position for remote agents 220 // Use the camera position for local agents and avatar position for remote agents
215 Vector3 presencePos = (presence.IsChildAgent) ? 221 // Why would I want that? They could be camming but I still see them at the
216 presence.AbsolutePosition : 222 // avatar position, so why should I update them as if they were at their
217 presence.CameraPosition; 223 // camera positions? Makes no sense!
224 // TODO: Fix this mess
225 //Vector3 presencePos = (presence.IsChildAgent) ?
226 // presence.AbsolutePosition :
227 // presence.CameraPosition;
228
229 Vector3 presencePos = presence.AbsolutePosition;
218 230
219 // Compute the distance... 231 // Compute the distance...
220 double distance = Vector3.Distance(presencePos, entityPos); 232 double distance = Vector3.Distance(presencePos, entityPos);
221 233
222 // And convert the distance to a priority queue, this computation gives queues 234 // And convert the distance to a priority queue, this computation gives queues
223 // at 10, 20, 40, 80, 160, 320, 640, and 1280m 235 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
224 uint pqueue = PriorityQueue.NumberOfImmediateQueues; 236 uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue
225 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; 237 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
226 238/*
227 for (int i = 0; i < queues - 1; i++) 239 for (int i = 0; i < queues - 1; i++)
228 { 240 {
229 if (distance < 10 * Math.Pow(2.0,i)) 241 if (distance < 30 * Math.Pow(2.0,i))
230 break; 242 break;
231 pqueue++; 243 pqueue++;
232 } 244 }
233 245*/
246 if (distance > 10f)
247 {
248 float tmp = (float)Math.Log((double)distance) * 1.4426950408889634073599246810019f - 3.3219280948873623478703194294894f;
249 // for a map identical to original:
250 // now
251 // 1st constant is 1/(log(2)) (natural log) so we get log2(distance)
252 // 2st constant makes it be log2(distance/10)
253 pqueue += (uint)tmp;
254 if (pqueue > queues - 1)
255 pqueue = queues - 1;
256 }
257
234 // If this is a root agent, then determine front & back 258 // If this is a root agent, then determine front & back
235 // Bump up the priority queue (drop the priority) for any objects behind the avatar 259 // Bump up the priority queue (drop the priority) for any objects behind the avatar
236 if (useFrontBack && ! presence.IsChildAgent) 260 if (useFrontBack && ! presence.IsChildAgent)
diff --git a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
new file mode 100644
index 0000000..10ac37c
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
@@ -0,0 +1,95 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.Framework.Scenes
34{
35 public static class SOPMaterialData
36 {
37 public enum SopMaterial : int // redundante and not in use for now
38 {
39 Stone = 0,
40 Metal = 1,
41 Glass = 2,
42 Wood = 3,
43 Flesh = 4,
44 Plastic = 5,
45 Rubber = 6,
46 light = 7 // compatibility with old viewers
47 }
48
49 private struct MaterialData
50 {
51 public float friction;
52 public float bounce;
53 public MaterialData(float f, float b)
54 {
55 friction = f;
56 bounce = b;
57 }
58 }
59
60 private static MaterialData[] m_materialdata = {
61 new MaterialData(0.8f,0.4f), // Stone
62 new MaterialData(0.3f,0.4f), // Metal
63 new MaterialData(0.2f,0.7f), // Glass
64 new MaterialData(0.6f,0.5f), // Wood
65 new MaterialData(0.9f,0.3f), // Flesh
66 new MaterialData(0.4f,0.7f), // Plastic
67 new MaterialData(0.9f,0.95f), // Rubber
68 new MaterialData(0.0f,0.0f) // light ??
69 };
70
71 public static Material MaxMaterial
72 {
73 get { return (Material)(m_materialdata.Length - 1); }
74 }
75
76 public static float friction(Material material)
77 {
78 int indx = (int)material;
79 if (indx < m_materialdata.Length)
80 return (m_materialdata[indx].friction);
81 else
82 return 0;
83 }
84
85 public static float bounce(Material material)
86 {
87 int indx = (int)material;
88 if (indx < m_materialdata.Length)
89 return (m_materialdata[indx].bounce);
90 else
91 return 0;
92 }
93
94 }
95} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
new file mode 100644
index 0000000..58f4641
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
@@ -0,0 +1,792 @@
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;
32using OpenSim.Region.PhysicsModules.SharedBase;
33using System.Text;
34using System.IO;
35using System.Xml;
36using OpenSim.Framework.Serialization;
37using OpenSim.Framework.Serialization.External;
38using OpenSim.Region.Framework.Scenes.Serialization;
39
40namespace OpenSim.Region.Framework.Scenes
41{
42 public class SOPVehicle
43 {
44 public VehicleData vd;
45
46 public Vehicle Type
47 {
48 get { return vd.m_type; }
49 }
50
51 public SOPVehicle()
52 {
53 vd = new VehicleData();
54 ProcessTypeChange(Vehicle.TYPE_NONE); // is needed?
55 }
56
57 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
58 {
59 float len;
60 float timestep = 0.01f;
61 switch (pParam)
62 {
63 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
64 if (pValue < 0f) pValue = 0f;
65 if (pValue > 1f) pValue = 1f;
66 vd.m_angularDeflectionEfficiency = pValue;
67 break;
68 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
69 if (pValue < timestep) pValue = timestep;
70 vd.m_angularDeflectionTimescale = pValue;
71 break;
72 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
73 if (pValue < timestep) pValue = timestep;
74 else if (pValue > 120) pValue = 120;
75 vd.m_angularMotorDecayTimescale = pValue;
76 break;
77 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
78 if (pValue < timestep) pValue = timestep;
79 vd.m_angularMotorTimescale = pValue;
80 break;
81 case Vehicle.BANKING_EFFICIENCY:
82 if (pValue < -1f) pValue = -1f;
83 if (pValue > 1f) pValue = 1f;
84 vd.m_bankingEfficiency = pValue;
85 break;
86 case Vehicle.BANKING_MIX:
87 if (pValue < 0f) pValue = 0f;
88 if (pValue > 1f) pValue = 1f;
89 vd.m_bankingMix = pValue;
90 break;
91 case Vehicle.BANKING_TIMESCALE:
92 if (pValue < timestep) pValue = timestep;
93 vd.m_bankingTimescale = pValue;
94 break;
95 case Vehicle.BUOYANCY:
96 if (pValue < -1f) pValue = -1f;
97 if (pValue > 1f) pValue = 1f;
98 vd.m_VehicleBuoyancy = pValue;
99 break;
100 case Vehicle.HOVER_EFFICIENCY:
101 if (pValue < 0f) pValue = 0f;
102 if (pValue > 1f) pValue = 1f;
103 vd.m_VhoverEfficiency = pValue;
104 break;
105 case Vehicle.HOVER_HEIGHT:
106 vd.m_VhoverHeight = pValue;
107 break;
108 case Vehicle.HOVER_TIMESCALE:
109 if (pValue < timestep) pValue = timestep;
110 vd.m_VhoverTimescale = pValue;
111 break;
112 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
113 if (pValue < 0f) pValue = 0f;
114 if (pValue > 1f) pValue = 1f;
115 vd.m_linearDeflectionEfficiency = pValue;
116 break;
117 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
118 if (pValue < timestep) pValue = timestep;
119 vd.m_linearDeflectionTimescale = pValue;
120 break;
121 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
122 if (pValue < timestep) pValue = timestep;
123 else if (pValue > 120) pValue = 120;
124 vd.m_linearMotorDecayTimescale = pValue;
125 break;
126 case Vehicle.LINEAR_MOTOR_TIMESCALE:
127 if (pValue < timestep) pValue = timestep;
128 vd.m_linearMotorTimescale = pValue;
129 break;
130 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
131 if (pValue < 0f) pValue = 0f;
132 if (pValue > 1f) pValue = 1f;
133 vd.m_verticalAttractionEfficiency = pValue;
134 break;
135 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
136 if (pValue < timestep) pValue = timestep;
137 vd.m_verticalAttractionTimescale = pValue;
138 break;
139
140 // These are vector properties but the engine lets you use a single float value to
141 // set all of the components to the same value
142 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
143 if (pValue < timestep) pValue = timestep;
144 vd.m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
145 break;
146 case Vehicle.ANGULAR_MOTOR_DIRECTION:
147 vd.m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
148 len = vd.m_angularMotorDirection.Length();
149 if (len > 12.566f)
150 vd.m_angularMotorDirection *= (12.566f / len);
151 break;
152 case Vehicle.LINEAR_FRICTION_TIMESCALE:
153 if (pValue < timestep) pValue = timestep;
154 vd.m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
155 break;
156 case Vehicle.LINEAR_MOTOR_DIRECTION:
157 vd.m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
158 len = vd.m_linearMotorDirection.Length();
159 if (len > 30.0f)
160 vd.m_linearMotorDirection *= (30.0f / len);
161 break;
162 case Vehicle.LINEAR_MOTOR_OFFSET:
163 vd.m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
164 len = vd.m_linearMotorOffset.Length();
165 if (len > 100.0f)
166 vd.m_linearMotorOffset *= (100.0f / len);
167 break;
168 }
169 }//end ProcessFloatVehicleParam
170
171 public void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
172 {
173 float len;
174 float timestep = 0.01f;
175 switch (pParam)
176 {
177 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
178 if (pValue.X < timestep) pValue.X = timestep;
179 if (pValue.Y < timestep) pValue.Y = timestep;
180 if (pValue.Z < timestep) pValue.Z = timestep;
181
182 vd.m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
183 break;
184 case Vehicle.ANGULAR_MOTOR_DIRECTION:
185 vd.m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
186 // Limit requested angular speed to 2 rps= 4 pi rads/sec
187 len = vd.m_angularMotorDirection.Length();
188 if (len > 12.566f)
189 vd.m_angularMotorDirection *= (12.566f / len);
190 break;
191 case Vehicle.LINEAR_FRICTION_TIMESCALE:
192 if (pValue.X < timestep) pValue.X = timestep;
193 if (pValue.Y < timestep) pValue.Y = timestep;
194 if (pValue.Z < timestep) pValue.Z = timestep;
195 vd.m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
196 break;
197 case Vehicle.LINEAR_MOTOR_DIRECTION:
198 vd.m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
199 len = vd.m_linearMotorDirection.Length();
200 if (len > 30.0f)
201 vd.m_linearMotorDirection *= (30.0f / len);
202 break;
203 case Vehicle.LINEAR_MOTOR_OFFSET:
204 vd.m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
205 len = vd.m_linearMotorOffset.Length();
206 if (len > 100.0f)
207 vd.m_linearMotorOffset *= (100.0f / len);
208 break;
209 }
210 }//end ProcessVectorVehicleParam
211
212 public void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
213 {
214 switch (pParam)
215 {
216 case Vehicle.REFERENCE_FRAME:
217 vd.m_referenceFrame = pValue;
218 break;
219 }
220 }//end ProcessRotationVehicleParam
221
222 public void ProcessVehicleFlags(int pParam, bool remove)
223 {
224 if (remove)
225 {
226 vd.m_flags &= ~((VehicleFlag)pParam);
227 }
228 else
229 {
230 vd.m_flags |= (VehicleFlag)pParam;
231 }
232 }//end ProcessVehicleFlags
233
234 public void ProcessTypeChange(Vehicle pType)
235 {
236 vd.m_linearMotorDirection = Vector3.Zero;
237 vd.m_angularMotorDirection = Vector3.Zero;
238 vd.m_linearMotorOffset = Vector3.Zero;
239 vd.m_referenceFrame = Quaternion.Identity;
240
241 // Set Defaults For Type
242 vd.m_type = pType;
243 switch (pType)
244 {
245 case Vehicle.TYPE_NONE:
246 vd.m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
247 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
248 vd.m_linearMotorTimescale = 1000;
249 vd.m_linearMotorDecayTimescale = 120;
250 vd.m_angularMotorTimescale = 1000;
251 vd.m_angularMotorDecayTimescale = 1000;
252 vd.m_VhoverHeight = 0;
253 vd.m_VhoverEfficiency = 1;
254 vd.m_VhoverTimescale = 1000;
255 vd.m_VehicleBuoyancy = 0;
256 vd.m_linearDeflectionEfficiency = 0;
257 vd.m_linearDeflectionTimescale = 1000;
258 vd.m_angularDeflectionEfficiency = 0;
259 vd.m_angularDeflectionTimescale = 1000;
260 vd.m_bankingEfficiency = 0;
261 vd.m_bankingMix = 1;
262 vd.m_bankingTimescale = 1000;
263 vd.m_verticalAttractionEfficiency = 0;
264 vd.m_verticalAttractionTimescale = 1000;
265
266 vd.m_flags = (VehicleFlag)0;
267 break;
268
269 case Vehicle.TYPE_SLED:
270 vd.m_linearFrictionTimescale = new Vector3(30, 1, 1000);
271 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
272 vd.m_linearMotorTimescale = 1000;
273 vd.m_linearMotorDecayTimescale = 120;
274 vd.m_angularMotorTimescale = 1000;
275 vd.m_angularMotorDecayTimescale = 120;
276 vd.m_VhoverHeight = 0;
277 vd.m_VhoverEfficiency = 1;
278 vd.m_VhoverTimescale = 10;
279 vd.m_VehicleBuoyancy = 0;
280 vd.m_linearDeflectionEfficiency = 1;
281 vd.m_linearDeflectionTimescale = 1;
282 vd.m_angularDeflectionEfficiency = 0;
283 vd.m_angularDeflectionTimescale = 1000;
284 vd.m_bankingEfficiency = 0;
285 vd.m_bankingMix = 1;
286 vd.m_bankingTimescale = 10;
287 vd.m_flags &=
288 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
289 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
290 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
291 break;
292 case Vehicle.TYPE_CAR:
293 vd.m_linearFrictionTimescale = new Vector3(100, 2, 1000);
294 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
295 vd.m_linearMotorTimescale = 1;
296 vd.m_linearMotorDecayTimescale = 60;
297 vd.m_angularMotorTimescale = 1;
298 vd.m_angularMotorDecayTimescale = 0.8f;
299 vd.m_VhoverHeight = 0;
300 vd.m_VhoverEfficiency = 0;
301 vd.m_VhoverTimescale = 1000;
302 vd.m_VehicleBuoyancy = 0;
303 vd.m_linearDeflectionEfficiency = 1;
304 vd.m_linearDeflectionTimescale = 2;
305 vd.m_angularDeflectionEfficiency = 0;
306 vd.m_angularDeflectionTimescale = 10;
307 vd.m_verticalAttractionEfficiency = 1f;
308 vd.m_verticalAttractionTimescale = 10f;
309 vd.m_bankingEfficiency = -0.2f;
310 vd.m_bankingMix = 1;
311 vd.m_bankingTimescale = 1;
312 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
313 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
314 VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
315 break;
316 case Vehicle.TYPE_BOAT:
317 vd.m_linearFrictionTimescale = new Vector3(10, 3, 2);
318 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
319 vd.m_linearMotorTimescale = 5;
320 vd.m_linearMotorDecayTimescale = 60;
321 vd.m_angularMotorTimescale = 4;
322 vd.m_angularMotorDecayTimescale = 4;
323 vd.m_VhoverHeight = 0;
324 vd.m_VhoverEfficiency = 0.5f;
325 vd.m_VhoverTimescale = 2;
326 vd.m_VehicleBuoyancy = 1;
327 vd.m_linearDeflectionEfficiency = 0.5f;
328 vd.m_linearDeflectionTimescale = 3;
329 vd.m_angularDeflectionEfficiency = 0.5f;
330 vd.m_angularDeflectionTimescale = 5;
331 vd.m_verticalAttractionEfficiency = 0.5f;
332 vd.m_verticalAttractionTimescale = 5f;
333 vd.m_bankingEfficiency = -0.3f;
334 vd.m_bankingMix = 0.8f;
335 vd.m_bankingTimescale = 1;
336 vd.m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
337 VehicleFlag.HOVER_GLOBAL_HEIGHT |
338 VehicleFlag.HOVER_UP_ONLY |
339 VehicleFlag.LIMIT_ROLL_ONLY);
340 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
341 VehicleFlag.LIMIT_MOTOR_UP |
342 VehicleFlag.HOVER_WATER_ONLY);
343 break;
344 case Vehicle.TYPE_AIRPLANE:
345 vd.m_linearFrictionTimescale = new Vector3(200, 10, 5);
346 vd.m_angularFrictionTimescale = new Vector3(20, 20, 20);
347 vd.m_linearMotorTimescale = 2;
348 vd.m_linearMotorDecayTimescale = 60;
349 vd.m_angularMotorTimescale = 4;
350 vd.m_angularMotorDecayTimescale = 8;
351 vd.m_VhoverHeight = 0;
352 vd.m_VhoverEfficiency = 0.5f;
353 vd.m_VhoverTimescale = 1000;
354 vd.m_VehicleBuoyancy = 0;
355 vd.m_linearDeflectionEfficiency = 0.5f;
356 vd.m_linearDeflectionTimescale = 0.5f;
357 vd.m_angularDeflectionEfficiency = 1;
358 vd.m_angularDeflectionTimescale = 2;
359 vd.m_verticalAttractionEfficiency = 0.9f;
360 vd.m_verticalAttractionTimescale = 2f;
361 vd.m_bankingEfficiency = 1;
362 vd.m_bankingMix = 0.7f;
363 vd.m_bankingTimescale = 2;
364 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
365 VehicleFlag.HOVER_TERRAIN_ONLY |
366 VehicleFlag.HOVER_GLOBAL_HEIGHT |
367 VehicleFlag.HOVER_UP_ONLY |
368 VehicleFlag.NO_DEFLECTION_UP |
369 VehicleFlag.LIMIT_MOTOR_UP);
370 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
371 break;
372 case Vehicle.TYPE_BALLOON:
373 vd.m_linearFrictionTimescale = new Vector3(5, 5, 5);
374 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
375 vd.m_linearMotorTimescale = 5;
376 vd.m_linearMotorDecayTimescale = 60;
377 vd.m_angularMotorTimescale = 6;
378 vd.m_angularMotorDecayTimescale = 10;
379 vd.m_VhoverHeight = 5;
380 vd.m_VhoverEfficiency = 0.8f;
381 vd.m_VhoverTimescale = 10;
382 vd.m_VehicleBuoyancy = 1;
383 vd.m_linearDeflectionEfficiency = 0;
384 vd.m_linearDeflectionTimescale = 5;
385 vd.m_angularDeflectionEfficiency = 0;
386 vd.m_angularDeflectionTimescale = 5;
387 vd.m_verticalAttractionEfficiency = 0f;
388 vd.m_verticalAttractionTimescale = 1000f;
389 vd.m_bankingEfficiency = 0;
390 vd.m_bankingMix = 0.7f;
391 vd.m_bankingTimescale = 5;
392 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
393 VehicleFlag.HOVER_TERRAIN_ONLY |
394 VehicleFlag.HOVER_UP_ONLY |
395 VehicleFlag.NO_DEFLECTION_UP |
396 VehicleFlag.LIMIT_MOTOR_UP);
397 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
398 VehicleFlag.HOVER_GLOBAL_HEIGHT);
399 break;
400 }
401 }
402 public void SetVehicle(PhysicsActor ph)
403 {
404 if (ph == null)
405 return;
406 ph.SetVehicle(vd);
407 }
408
409 private XmlTextWriter writer;
410
411 private void XWint(string name, int i)
412 {
413 writer.WriteElementString(name, i.ToString());
414 }
415
416 private void XWfloat(string name, float f)
417 {
418 writer.WriteElementString(name, f.ToString(Utils.EnUsCulture));
419 }
420
421 private void XWVector(string name, Vector3 vec)
422 {
423 writer.WriteStartElement(name);
424 writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
425 writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
426 writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
427 writer.WriteEndElement();
428 }
429
430 private void XWQuat(string name, Quaternion quat)
431 {
432 writer.WriteStartElement(name);
433 writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
434 writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
435 writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
436 writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
437 writer.WriteEndElement();
438 }
439
440 public void ToXml2(XmlTextWriter twriter)
441 {
442 writer = twriter;
443 writer.WriteStartElement("Vehicle");
444
445 XWint("TYPE", (int)vd.m_type);
446 XWint("FLAGS", (int)vd.m_flags);
447
448 // Linear properties
449 XWVector("LMDIR", vd.m_linearMotorDirection);
450 XWVector("LMFTIME", vd.m_linearFrictionTimescale);
451 XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
452 XWfloat("LMTIME", vd.m_linearMotorTimescale);
453 XWVector("LMOFF", vd.m_linearMotorOffset);
454
455 //Angular properties
456 XWVector("AMDIR", vd.m_angularMotorDirection);
457 XWfloat("AMTIME", vd.m_angularMotorTimescale);
458 XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
459 XWVector("AMFTIME", vd.m_angularFrictionTimescale);
460
461 //Deflection properties
462 XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
463 XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
464 XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
465 XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
466
467 //Banking properties
468 XWfloat("BEFF", vd.m_bankingEfficiency);
469 XWfloat("BMIX", vd.m_bankingMix);
470 XWfloat("BTIME", vd.m_bankingTimescale);
471
472 //Hover and Buoyancy properties
473 XWfloat("HHEI", vd.m_VhoverHeight);
474 XWfloat("HEFF", vd.m_VhoverEfficiency);
475 XWfloat("HTIME", vd.m_VhoverTimescale);
476 XWfloat("VBUO", vd.m_VehicleBuoyancy);
477
478 //Attractor properties
479 XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
480 XWfloat("VATIME", vd.m_verticalAttractionTimescale);
481
482 XWQuat("REF_FRAME", vd.m_referenceFrame);
483
484 writer.WriteEndElement();
485 writer = null;
486 }
487
488
489
490 XmlReader reader;
491
492 private int XRint()
493 {
494 return reader.ReadElementContentAsInt();
495 }
496
497 private float XRfloat()
498 {
499 return reader.ReadElementContentAsFloat();
500 }
501
502 public Vector3 XRvector()
503 {
504 Vector3 vec;
505 reader.ReadStartElement();
506 vec.X = reader.ReadElementContentAsFloat();
507 vec.Y = reader.ReadElementContentAsFloat();
508 vec.Z = reader.ReadElementContentAsFloat();
509 reader.ReadEndElement();
510 return vec;
511 }
512
513 public Quaternion XRquat()
514 {
515 Quaternion q;
516 reader.ReadStartElement();
517 q.X = reader.ReadElementContentAsFloat();
518 q.Y = reader.ReadElementContentAsFloat();
519 q.Z = reader.ReadElementContentAsFloat();
520 q.W = reader.ReadElementContentAsFloat();
521 reader.ReadEndElement();
522 return q;
523 }
524
525 public static bool EReadProcessors(
526 Dictionary<string, Action> processors,
527 XmlReader xtr)
528 {
529 bool errors = false;
530
531 string nodeName = string.Empty;
532 while (xtr.NodeType != XmlNodeType.EndElement)
533 {
534 nodeName = xtr.Name;
535
536 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName);
537
538 Action p = null;
539 if (processors.TryGetValue(xtr.Name, out p))
540 {
541 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName);
542
543 try
544 {
545 p();
546 }
547 catch (Exception e)
548 {
549 errors = true;
550 if (xtr.NodeType == XmlNodeType.EndElement)
551 xtr.Read();
552 }
553 }
554 else
555 {
556 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName);
557 xtr.ReadOuterXml(); // ignore
558 }
559 }
560
561 return errors;
562 }
563
564
565 public string ToXml2()
566 {
567 using (StringWriter sw = new StringWriter())
568 {
569 using (XmlTextWriter xwriter = new XmlTextWriter(sw))
570 {
571 ToXml2(xwriter);
572 }
573
574 return sw.ToString();
575 }
576 }
577
578 public static SOPVehicle FromXml2(string text)
579 {
580 if (text == String.Empty)
581 return null;
582
583 UTF8Encoding enc = new UTF8Encoding();
584 MemoryStream ms = new MemoryStream(enc.GetBytes(text));
585 XmlTextReader xreader = new XmlTextReader(ms);
586
587 SOPVehicle v = new SOPVehicle();
588 bool error;
589
590 v.FromXml2(xreader, out error);
591
592 xreader.Close();
593
594 if (error)
595 {
596 v = null;
597 return null;
598 }
599 return v;
600 }
601
602 public static SOPVehicle FromXml2(XmlReader reader)
603 {
604 SOPVehicle vehicle = new SOPVehicle();
605
606 bool errors = false;
607
608 vehicle.FromXml2(reader, out errors);
609 if (errors)
610 return null;
611
612 return vehicle;
613 }
614
615 private void FromXml2(XmlReader _reader, out bool errors)
616 {
617 errors = false;
618 reader = _reader;
619
620 Dictionary<string, Action> m_VehicleXmlProcessors
621 = new Dictionary<string, Action>();
622
623 m_VehicleXmlProcessors.Add("TYPE", ProcessXR_type);
624 m_VehicleXmlProcessors.Add("FLAGS", ProcessXR_flags);
625
626 // Linear properties
627 m_VehicleXmlProcessors.Add("LMDIR", ProcessXR_linearMotorDirection);
628 m_VehicleXmlProcessors.Add("LMFTIME", ProcessXR_linearFrictionTimescale);
629 m_VehicleXmlProcessors.Add("LMDTIME", ProcessXR_linearMotorDecayTimescale);
630 m_VehicleXmlProcessors.Add("LMTIME", ProcessXR_linearMotorTimescale);
631 m_VehicleXmlProcessors.Add("LMOFF", ProcessXR_linearMotorOffset);
632
633 //Angular properties
634 m_VehicleXmlProcessors.Add("AMDIR", ProcessXR_angularMotorDirection);
635 m_VehicleXmlProcessors.Add("AMTIME", ProcessXR_angularMotorTimescale);
636 m_VehicleXmlProcessors.Add("AMDTIME", ProcessXR_angularMotorDecayTimescale);
637 m_VehicleXmlProcessors.Add("AMFTIME", ProcessXR_angularFrictionTimescale);
638
639 //Deflection properties
640 m_VehicleXmlProcessors.Add("ADEFF", ProcessXR_angularDeflectionEfficiency);
641 m_VehicleXmlProcessors.Add("ADTIME", ProcessXR_angularDeflectionTimescale);
642 m_VehicleXmlProcessors.Add("LDEFF", ProcessXR_linearDeflectionEfficiency);
643 m_VehicleXmlProcessors.Add("LDTIME", ProcessXR_linearDeflectionTimescale);
644
645 //Banking properties
646 m_VehicleXmlProcessors.Add("BEFF", ProcessXR_bankingEfficiency);
647 m_VehicleXmlProcessors.Add("BMIX", ProcessXR_bankingMix);
648 m_VehicleXmlProcessors.Add("BTIME", ProcessXR_bankingTimescale);
649
650 //Hover and Buoyancy properties
651 m_VehicleXmlProcessors.Add("HHEI", ProcessXR_VhoverHeight);
652 m_VehicleXmlProcessors.Add("HEFF", ProcessXR_VhoverEfficiency);
653 m_VehicleXmlProcessors.Add("HTIME", ProcessXR_VhoverTimescale);
654
655 m_VehicleXmlProcessors.Add("VBUO", ProcessXR_VehicleBuoyancy);
656
657 //Attractor properties
658 m_VehicleXmlProcessors.Add("VAEFF", ProcessXR_verticalAttractionEfficiency);
659 m_VehicleXmlProcessors.Add("VATIME", ProcessXR_verticalAttractionTimescale);
660
661 m_VehicleXmlProcessors.Add("REF_FRAME", ProcessXR_referenceFrame);
662
663 vd = new VehicleData();
664
665 reader.ReadStartElement("Vehicle", String.Empty);
666
667 errors = EReadProcessors(
668 m_VehicleXmlProcessors,
669 reader);
670
671 reader.ReadEndElement();
672 reader = null;
673 }
674
675 private void ProcessXR_type()
676 {
677 vd.m_type = (Vehicle)XRint();
678 }
679 private void ProcessXR_flags()
680 {
681 vd.m_flags = (VehicleFlag)XRint();
682 }
683 // Linear properties
684 private void ProcessXR_linearMotorDirection()
685 {
686 vd.m_linearMotorDirection = XRvector();
687 }
688
689 private void ProcessXR_linearFrictionTimescale()
690 {
691 vd.m_linearFrictionTimescale = XRvector();
692 }
693
694 private void ProcessXR_linearMotorDecayTimescale()
695 {
696 vd.m_linearMotorDecayTimescale = XRfloat();
697 }
698 private void ProcessXR_linearMotorTimescale()
699 {
700 vd.m_linearMotorTimescale = XRfloat();
701 }
702 private void ProcessXR_linearMotorOffset()
703 {
704 vd.m_linearMotorOffset = XRvector();
705 }
706
707
708 //Angular properties
709 private void ProcessXR_angularMotorDirection()
710 {
711 vd.m_angularMotorDirection = XRvector();
712 }
713 private void ProcessXR_angularMotorTimescale()
714 {
715 vd.m_angularMotorTimescale = XRfloat();
716 }
717 private void ProcessXR_angularMotorDecayTimescale()
718 {
719 vd.m_angularMotorDecayTimescale = XRfloat();
720 }
721 private void ProcessXR_angularFrictionTimescale()
722 {
723 vd.m_angularFrictionTimescale = XRvector();
724 }
725
726 //Deflection properties
727 private void ProcessXR_angularDeflectionEfficiency()
728 {
729 vd.m_angularDeflectionEfficiency = XRfloat();
730 }
731 private void ProcessXR_angularDeflectionTimescale()
732 {
733 vd.m_angularDeflectionTimescale = XRfloat();
734 }
735 private void ProcessXR_linearDeflectionEfficiency()
736 {
737 vd.m_linearDeflectionEfficiency = XRfloat();
738 }
739 private void ProcessXR_linearDeflectionTimescale()
740 {
741 vd.m_linearDeflectionTimescale = XRfloat();
742 }
743
744 //Banking properties
745 private void ProcessXR_bankingEfficiency()
746 {
747 vd.m_bankingEfficiency = XRfloat();
748 }
749 private void ProcessXR_bankingMix()
750 {
751 vd.m_bankingMix = XRfloat();
752 }
753 private void ProcessXR_bankingTimescale()
754 {
755 vd.m_bankingTimescale = XRfloat();
756 }
757
758 //Hover and Buoyancy properties
759 private void ProcessXR_VhoverHeight()
760 {
761 vd.m_VhoverHeight = XRfloat();
762 }
763 private void ProcessXR_VhoverEfficiency()
764 {
765 vd.m_VhoverEfficiency = XRfloat();
766 }
767 private void ProcessXR_VhoverTimescale()
768 {
769 vd.m_VhoverTimescale = XRfloat();
770 }
771
772 private void ProcessXR_VehicleBuoyancy()
773 {
774 vd.m_VehicleBuoyancy = XRfloat();
775 }
776
777 //Attractor properties
778 private void ProcessXR_verticalAttractionEfficiency()
779 {
780 vd.m_verticalAttractionEfficiency = XRfloat();
781 }
782 private void ProcessXR_verticalAttractionTimescale()
783 {
784 vd.m_verticalAttractionTimescale = XRfloat();
785 }
786
787 private void ProcessXR_referenceFrame()
788 {
789 vd.m_referenceFrame = XRquat();
790 }
791 }
792}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index b838177..edb881f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -106,12 +106,12 @@ namespace OpenSim.Region.Framework.Scenes
106 engine.StartProcessing(); 106 engine.StartProcessing();
107 } 107 }
108 108
109 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) 109 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item, uint cost)
110 { 110 {
111 IMoneyModule money = RequestModuleInterface<IMoneyModule>(); 111 IMoneyModule money = RequestModuleInterface<IMoneyModule>();
112 if (money != null) 112 if (money != null)
113 { 113 {
114 money.ApplyUploadCharge(agentID, money.UploadCharge, "Asset upload"); 114 money.ApplyUploadCharge(agentID, (int)cost, "Asset upload");
115 } 115 }
116 116
117 AddInventoryItem(item); 117 AddInventoryItem(item);
@@ -182,7 +182,7 @@ namespace OpenSim.Region.Framework.Scenes
182 return false; 182 return false;
183 } 183 }
184 } 184 }
185 185
186 if (InventoryService.AddItem(item)) 186 if (InventoryService.AddItem(item))
187 { 187 {
188 int userlevel = 0; 188 int userlevel = 0;
@@ -338,8 +338,7 @@ namespace OpenSim.Region.Framework.Scenes
338 338
339 // Update item with new asset 339 // Update item with new asset
340 item.AssetID = asset.FullID; 340 item.AssetID = asset.FullID;
341 if (group.UpdateInventoryItem(item)) 341 group.UpdateInventoryItem(item);
342 remoteClient.SendAlertMessage("Script saved");
343 342
344 part.SendPropertiesToClient(remoteClient); 343 part.SendPropertiesToClient(remoteClient);
345 344
@@ -350,12 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
350 { 349 {
351 // Needs to determine which engine was running it and use that 350 // Needs to determine which engine was running it and use that
352 // 351 //
353 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 352 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 1);
354 errors = part.Inventory.GetScriptErrors(item.ItemID);
355 }
356 else
357 {
358 remoteClient.SendAlertMessage("Script saved");
359 } 353 }
360 354
361 // Tell anyone managing scripts that a script has been reloaded/changed 355 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -421,6 +415,7 @@ namespace OpenSim.Region.Framework.Scenes
421 if (item.Owner != remoteClient.AgentId) 415 if (item.Owner != remoteClient.AgentId)
422 return; 416 return;
423 417
418 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
424 item.Name = itemUpd.Name; 419 item.Name = itemUpd.Name;
425 item.Description = itemUpd.Description; 420 item.Description = itemUpd.Description;
426 421
@@ -889,6 +884,20 @@ namespace OpenSim.Region.Framework.Scenes
889 if (newName == String.Empty) 884 if (newName == String.Empty)
890 newName = item.Name; 885 newName = item.Name;
891 886
887 AssetBase asset = AssetService.Get(item.AssetID.ToString());
888
889 if (asset != null)
890 {
891 if (newName != String.Empty)
892 {
893 asset.Name = newName;
894 }
895 else
896 {
897 newName = item.Name;
898 }
899
900
892 if (remoteClient.AgentId == oldAgentID 901 if (remoteClient.AgentId == oldAgentID
893 || (LibraryService != null 902 || (LibraryService != null
894 && LibraryService.LibraryRootFolder != null 903 && LibraryService.LibraryRootFolder != null
@@ -915,6 +924,13 @@ namespace OpenSim.Region.Framework.Scenes
915 } 924 }
916 } 925 }
917 } 926 }
927 else
928 {
929 m_log.ErrorFormat(
930 "[AGENT INVENTORY]: Could not copy item {0} since asset {1} could not be found",
931 item.Name, item.AssetID);
932 }
933 }
918 934
919 /// <summary> 935 /// <summary>
920 /// Create a new asset data structure. 936 /// Create a new asset data structure.
@@ -929,6 +945,24 @@ namespace OpenSim.Region.Framework.Scenes
929 } 945 }
930 946
931 /// <summary> 947 /// <summary>
948 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
949 /// </summary>
950 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
951 {
952 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
953 foreach (InventoryItemBase b in items)
954 {
955 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
956 InventoryItemBase n = InventoryService.GetItem(b);
957 n.Folder = destfolder;
958 moveitems.Add(n);
959 remoteClient.SendInventoryItemCreateUpdate(n, 0);
960 }
961
962 MoveInventoryItem(remoteClient, moveitems);
963 }
964
965 /// <summary>
932 /// Move an item within the agent's inventory. 966 /// Move an item within the agent's inventory.
933 /// </summary> 967 /// </summary>
934 /// <param name="remoteClient"></param> 968 /// <param name="remoteClient"></param>
@@ -1015,7 +1049,11 @@ namespace OpenSim.Region.Framework.Scenes
1015 item.BasePermissions = baseMask; 1049 item.BasePermissions = baseMask;
1016 item.CreationDate = creationDate; 1050 item.CreationDate = creationDate;
1017 1051
1018 if (AddInventoryItem(item, assetUpload)) 1052 // special AnimationSet case
1053 if (item.InvType == (int)CustomInventoryType.AnimationSet)
1054 AnimationSet.enforceItemPermitions(item,true);
1055
1056 if (AddInventoryItem(item))
1019 { 1057 {
1020 remoteClient.SendInventoryItemCreateUpdate(item, callbackID); 1058 remoteClient.SendInventoryItemCreateUpdate(item, callbackID);
1021 } 1059 }
@@ -1327,6 +1365,10 @@ namespace OpenSim.Region.Framework.Scenes
1327 { 1365 {
1328 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1366 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1329 1367
1368 // Can't move a null item
1369 if (itemId == UUID.Zero)
1370 return;
1371
1330 if (null == part) 1372 if (null == part)
1331 { 1373 {
1332 m_log.WarnFormat( 1374 m_log.WarnFormat(
@@ -1437,21 +1479,28 @@ namespace OpenSim.Region.Framework.Scenes
1437 return; 1479 return;
1438 } 1480 }
1439 1481
1440 if (part.OwnerID != destPart.OwnerID) 1482 // Can't transfer this
1483 //
1484 if (part.OwnerID != destPart.OwnerID && (srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1485 return;
1486
1487 bool overrideNoMod = false;
1488 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1489 overrideNoMod = true;
1490
1491 if (part.OwnerID != destPart.OwnerID && (destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1441 { 1492 {
1442 // Source must have transfer permissions 1493 // object cannot copy items to an object owned by a different owner
1443 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) 1494 // unless llAllowInventoryDrop has been called
1444 return;
1445 1495
1446 // Object cannot copy items to an object owned by a different owner 1496 return;
1447 // unless llAllowInventoryDrop has been called on the destination
1448 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1449 return;
1450 } 1497 }
1451 1498
1452 // must have both move and modify permission to put an item in an object 1499 // must have both move and modify permission to put an item in an object
1453 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1500 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1501 {
1454 return; 1502 return;
1503 }
1455 1504
1456 TaskInventoryItem destTaskItem = new TaskInventoryItem(); 1505 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1457 1506
@@ -1507,10 +1556,20 @@ namespace OpenSim.Region.Framework.Scenes
1507 1556
1508 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1557 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1509 { 1558 {
1559
1510 ScenePresence avatar; 1560 ScenePresence avatar;
1511 IClientAPI remoteClient = null; 1561 IClientAPI remoteClient = null;
1512 if (TryGetScenePresence(destID, out avatar)) 1562 if (TryGetScenePresence(destID, out avatar))
1513 remoteClient = avatar.ControllingClient; 1563 remoteClient = avatar.ControllingClient;
1564// ????
1565 SceneObjectPart destPart = GetSceneObjectPart(destID);
1566 if (destPart != null) // Move into a prim
1567 {
1568 foreach(UUID itemID in items)
1569 MoveTaskInventoryItem(destID, host, itemID);
1570 return destID; // Prim folder ID == prim ID
1571 }
1572// /????
1514 1573
1515 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1574 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1516 1575
@@ -1696,12 +1755,12 @@ namespace OpenSim.Region.Framework.Scenes
1696 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction( 1755 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction(
1697 remoteClient, part, transactionID, currentItem); 1756 remoteClient, part, transactionID, currentItem);
1698 1757
1699 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1758// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1700 remoteClient.SendAlertMessage("Notecard saved"); 1759// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1701 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1760// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1702 remoteClient.SendAlertMessage("Script saved"); 1761// remoteClient.SendAgentAlertMessage("Script saved", false);
1703 else 1762// else
1704 remoteClient.SendAlertMessage("Item saved"); 1763// remoteClient.SendAgentAlertMessage("Item saved", false);
1705 } 1764 }
1706 1765
1707 // Base ALWAYS has move 1766 // Base ALWAYS has move
@@ -2075,7 +2134,8 @@ namespace OpenSim.Region.Framework.Scenes
2075 // build a list of eligible objects 2134 // build a list of eligible objects
2076 List<uint> deleteIDs = new List<uint>(); 2135 List<uint> deleteIDs = new List<uint>();
2077 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 2136 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
2078 2137 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
2138
2079 // Start with true for both, then remove the flags if objects 2139 // Start with true for both, then remove the flags if objects
2080 // that we can't derez are part of the selection 2140 // that we can't derez are part of the selection
2081 bool permissionToTake = true; 2141 bool permissionToTake = true;
@@ -2084,14 +2144,24 @@ namespace OpenSim.Region.Framework.Scenes
2084 2144
2085 foreach (uint localID in localIDs) 2145 foreach (uint localID in localIDs)
2086 { 2146 {
2147
2148
2087 // Invalid id 2149 // Invalid id
2088 SceneObjectPart part = GetSceneObjectPart(localID); 2150 SceneObjectPart part = GetSceneObjectPart(localID);
2089 if (part == null) 2151 if (part == null)
2152 {
2153 //Client still thinks the object exists, kill it
2154 deleteIDs.Add(localID);
2090 continue; 2155 continue;
2156 }
2091 2157
2092 // Already deleted by someone else 2158 // Already deleted by someone else
2093 if (part.ParentGroup.IsDeleted) 2159 if (part.ParentGroup.IsDeleted)
2160 {
2161 //Client still thinks the object exists, kill it
2162 deleteIDs.Add(localID);
2094 continue; 2163 continue;
2164 }
2095 2165
2096 // Can't delete child prims 2166 // Can't delete child prims
2097 if (part != part.ParentGroup.RootPart) 2167 if (part != part.ParentGroup.RootPart)
@@ -2099,9 +2169,6 @@ namespace OpenSim.Region.Framework.Scenes
2099 2169
2100 SceneObjectGroup grp = part.ParentGroup; 2170 SceneObjectGroup grp = part.ParentGroup;
2101 2171
2102 deleteIDs.Add(localID);
2103 deleteGroups.Add(grp);
2104
2105 // If child prims have invalid perms, fix them 2172 // If child prims have invalid perms, fix them
2106 grp.AdjustChildPrimPermissions(false); 2173 grp.AdjustChildPrimPermissions(false);
2107 2174
@@ -2121,87 +2188,191 @@ namespace OpenSim.Region.Framework.Scenes
2121 } 2188 }
2122 else 2189 else
2123 { 2190 {
2124 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 2191 if (action == DeRezAction.TakeCopy)
2192 {
2193 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
2194 permissionToTakeCopy = false;
2195 }
2196 else
2197 {
2125 permissionToTakeCopy = false; 2198 permissionToTakeCopy = false;
2126 2199 }
2127 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 2200 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
2128 permissionToTake = false; 2201 permissionToTake = false;
2129 2202
2130 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 2203 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
2131 permissionToDelete = false; 2204 permissionToDelete = false;
2132 } 2205 }
2133 }
2134 2206
2135 // Handle god perms 2207 // Handle god perms
2136 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 2208 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
2137 {
2138 permissionToTake = true;
2139 permissionToTakeCopy = true;
2140 permissionToDelete = true;
2141 }
2142
2143 // If we're re-saving, we don't even want to delete
2144 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2145 permissionToDelete = false;
2146
2147 // if we want to take a copy, we also don't want to delete
2148 // Note: after this point, the permissionToTakeCopy flag
2149 // becomes irrelevant. It already includes the permissionToTake
2150 // permission and after excluding no copy items here, we can
2151 // just use that.
2152 if (action == DeRezAction.TakeCopy)
2153 {
2154 // If we don't have permission, stop right here
2155 if (!permissionToTakeCopy)
2156 { 2209 {
2157 remoteClient.SendAlertMessage("You don't have permission to take the object"); 2210 permissionToTake = true;
2158 return; 2211 permissionToTakeCopy = true;
2212 permissionToDelete = true;
2159 } 2213 }
2160 2214
2161 permissionToTake = true; 2215 // If we're re-saving, we don't even want to delete
2162 // Don't delete 2216 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2163 permissionToDelete = false; 2217 permissionToDelete = false;
2164 }
2165 2218
2166 if (action == DeRezAction.Return) 2219 // if we want to take a copy, we also don't want to delete
2167 { 2220 // Note: after this point, the permissionToTakeCopy flag
2168 if (remoteClient != null) 2221 // becomes irrelevant. It already includes the permissionToTake
2222 // permission and after excluding no copy items here, we can
2223 // just use that.
2224 if (action == DeRezAction.TakeCopy)
2169 { 2225 {
2170 if (Permissions.CanReturnObjects( 2226 // If we don't have permission, stop right here
2171 null, 2227 if (!permissionToTakeCopy)
2172 remoteClient.AgentId,
2173 deleteGroups))
2174 { 2228 {
2175 permissionToTake = true; 2229 remoteClient.SendAlertMessage("You don't have permission to take the object");
2176 permissionToDelete = true; 2230 return;
2231 }
2177 2232
2178 foreach (SceneObjectGroup g in deleteGroups) 2233 permissionToTake = true;
2234 // Don't delete
2235 permissionToDelete = false;
2236 }
2237
2238 if (action == DeRezAction.Return)
2239 {
2240 if (remoteClient != null)
2241 {
2242 if (Permissions.CanReturnObjects(
2243 null,
2244 remoteClient.AgentId,
2245 new List<SceneObjectGroup>() {grp}))
2179 { 2246 {
2180 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 2247 permissionToTake = true;
2248 permissionToDelete = true;
2249
2250 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
2181 } 2251 }
2182 } 2252 }
2253 else // Auto return passes through here with null agent
2254 {
2255 permissionToTake = true;
2256 permissionToDelete = true;
2257 }
2183 } 2258 }
2184 else // Auto return passes through here with null agent 2259
2260 if (permissionToTake && (!permissionToDelete))
2261 takeGroups.Add(grp);
2262
2263 if (permissionToDelete)
2185 { 2264 {
2186 permissionToTake = true; 2265 if (permissionToTake)
2187 permissionToDelete = true; 2266 deleteGroups.Add(grp);
2267 deleteIDs.Add(grp.LocalId);
2188 } 2268 }
2189 } 2269 }
2190 2270
2191 // OK, we're done with permissions. Let's check if any part of the code prevents the objects from being deleted 2271 SendKillObject(deleteIDs);
2192 bool canDelete = EventManager.TriggerDeRezRequested(remoteClient, deleteGroups, action);
2193 2272
2194 if (permissionToTake && (action != DeRezAction.Delete || this.m_useTrashOnDelete)) 2273 if (deleteGroups.Count > 0)
2195 { 2274 {
2275 foreach (SceneObjectGroup g in deleteGroups)
2276 deleteIDs.Remove(g.LocalId);
2277
2196 m_asyncSceneObjectDeleter.DeleteToInventory( 2278 m_asyncSceneObjectDeleter.DeleteToInventory(
2197 action, destinationID, deleteGroups, remoteClient, 2279 action, destinationID, deleteGroups, remoteClient,
2198 permissionToDelete && canDelete); 2280 true);
2199 } 2281 }
2200 else if (permissionToDelete && canDelete) 2282 if (takeGroups.Count > 0)
2283 {
2284 m_asyncSceneObjectDeleter.DeleteToInventory(
2285 action, destinationID, takeGroups, remoteClient,
2286 false);
2287 }
2288 if (deleteIDs.Count > 0)
2201 { 2289 {
2202 foreach (SceneObjectGroup g in deleteGroups) 2290 foreach (SceneObjectGroup g in deleteGroups)
2203 DeleteSceneObject(g, false); 2291 DeleteSceneObject(g, true);
2292 }
2293 }
2294
2295 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2296 {
2297 itemID = UUID.Zero;
2298 if (grp != null)
2299 {
2300 Vector3 inventoryStoredPosition = new Vector3(
2301 Math.Min(grp.AbsolutePosition.X, RegionInfo.RegionSizeX - 6),
2302 Math.Min(grp.AbsolutePosition.Y, RegionInfo.RegionSizeY - 6),
2303 grp.AbsolutePosition.Z);
2304
2305 Vector3 originalPosition = grp.AbsolutePosition;
2306
2307 grp.AbsolutePosition = inventoryStoredPosition;
2308
2309 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2310
2311 grp.AbsolutePosition = originalPosition;
2312
2313 AssetBase asset = CreateAsset(
2314 grp.GetPartName(grp.LocalId),
2315 grp.GetPartDescription(grp.LocalId),
2316 (sbyte)AssetType.Object,
2317 Utils.StringToBytes(sceneObjectXml),
2318 remoteClient.AgentId);
2319 AssetService.Store(asset);
2320
2321 InventoryItemBase item = new InventoryItemBase();
2322 item.CreatorId = grp.RootPart.CreatorID.ToString();
2323 item.CreatorData = grp.RootPart.CreatorData;
2324 item.Owner = remoteClient.AgentId;
2325 item.ID = UUID.Random();
2326 item.AssetID = asset.FullID;
2327 item.Description = asset.Description;
2328 item.Name = asset.Name;
2329 item.AssetType = asset.Type;
2330 item.InvType = (int)InventoryType.Object;
2331
2332 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, FolderType.Object);
2333 if (folder != null)
2334 item.Folder = folder.ID;
2335 else // oopsies
2336 item.Folder = UUID.Zero;
2337
2338 // Set up base perms properly
2339 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2340 permsBase &= grp.RootPart.BaseMask;
2341 permsBase |= (uint)PermissionMask.Move;
2342
2343 // Make sure we don't lock it
2344 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2345
2346 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2347 {
2348 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2349 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2350 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2351 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2352 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2353 }
2354 else
2355 {
2356 item.BasePermissions = permsBase;
2357 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2358 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2359 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2360 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2361 }
2362 item.CreationDate = Util.UnixTimeSinceEpoch();
2363
2364 // sets itemID so client can show item as 'attached' in inventory
2365 grp.FromItemID = item.ID;
2366
2367 if (AddInventoryItem(item))
2368 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2369 else
2370 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2371
2372 itemID = item.ID;
2373 return item.AssetID;
2204 } 2374 }
2375 return UUID.Zero;
2205 } 2376 }
2206 2377
2207 /// <summary> 2378 /// <summary>
@@ -2254,7 +2425,7 @@ namespace OpenSim.Region.Framework.Scenes
2254 Util.LogFailedXML("[AGENT INVENTORY]:", xmlData); 2425 Util.LogFailedXML("[AGENT INVENTORY]:", xmlData);
2255 g = null; 2426 g = null;
2256 } 2427 }
2257 2428
2258 if (g != null) 2429 if (g != null)
2259 { 2430 {
2260 objlist.Add(g); 2431 objlist.Add(g);
@@ -2265,7 +2436,7 @@ namespace OpenSim.Region.Framework.Scenes
2265 return true; 2436 return true;
2266 } 2437 }
2267 else 2438 else
2268 { 2439 {
2269 XmlDocument doc = new XmlDocument(); 2440 XmlDocument doc = new XmlDocument();
2270 doc.LoadXml(xmlData); 2441 doc.LoadXml(xmlData);
2271 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); 2442 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
@@ -2371,7 +2542,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 2542 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2372 BypassRayCast, bRayEndIsIntersection, true, scale, false); 2543 BypassRayCast, bRayEndIsIntersection, true, scale, false);
2373 2544
2374 RezObject(part, item, pos, null, Vector3.Zero, 0); 2545 RezObject(part, item, pos, null, Vector3.Zero, 0, false);
2375 } 2546 }
2376 } 2547 }
2377 2548
@@ -2387,15 +2558,18 @@ namespace OpenSim.Region.Framework.Scenes
2387 /// <param name="param"></param> 2558 /// <param name="param"></param>
2388 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns> 2559 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2389 public virtual List<SceneObjectGroup> RezObject( 2560 public virtual List<SceneObjectGroup> RezObject(
2390 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2561 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param, bool atRoot)
2391 { 2562 {
2392 if (null == item) 2563 if (null == item)
2393 return null; 2564 return null;
2394 2565
2395 List<SceneObjectGroup> objlist; 2566 List<SceneObjectGroup> objlist;
2396 List<Vector3> veclist; 2567 List<Vector3> veclist;
2397 2568 Vector3 bbox;
2398 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist); 2569 float offsetHeight;
2570
2571 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist,out bbox, out offsetHeight);
2572
2399 if (!success) 2573 if (!success)
2400 return null; 2574 return null;
2401 2575
@@ -2412,10 +2586,69 @@ namespace OpenSim.Region.Framework.Scenes
2412 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2586 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2413 } 2587 }
2414 2588
2589 SceneObjectGroup sog;
2590
2591 bool fixrot = false;
2592 Quaternion netRot = Quaternion.Identity;
2593
2594 // position adjust
2595 if (totalPrims > 1) // nothing to do on a single prim
2596 {
2597 if (objlist.Count == 1)
2598 {
2599 // current object position is root position
2600 if(!atRoot)
2601 {
2602 sog = objlist[0];
2603 Quaternion orot;
2604 if (rot == null)
2605 orot = sog.RootPart.GetWorldRotation();
2606 else
2607 orot = rot.Value;
2608 // possible should be bbox, but geometric center looks better
2609 Vector3 off = sog.GetGeometricCenter();
2610// Vector3 off = bbox * 0.5f;
2611 off *= orot;
2612 pos -= off;
2613 }
2614 }
2615 else
2616 {
2617 //veclist[] are relative to bbox corner with min X,Y and Z
2618 // rez at root, and rot will be referenced to first object in list
2619 if (rot == null)
2620 {
2621 // use original rotations
2622 if (atRoot)
2623 pos -= veclist[0];
2624 else
2625 pos -= bbox / 2;
2626 }
2627 else
2628 {
2629 fixrot = true;
2630 sog = objlist[0];
2631 netRot = Quaternion.Conjugate(sog.RootPart.GetWorldRotation());
2632 netRot = netRot * rot.Value;
2633 Vector3 off;
2634 if (atRoot)
2635 off = veclist[0];
2636 else
2637 off = bbox / 2;
2638 off *= netRot;
2639 pos -= off;
2640 }
2641 }
2642 }
2643
2415 for (int i = 0; i < objlist.Count; i++) 2644 for (int i = 0; i < objlist.Count; i++)
2416 { 2645 {
2417 SceneObjectGroup group = objlist[i]; 2646 SceneObjectGroup group = objlist[i];
2418 Vector3 curpos = pos + veclist[i]; 2647 Vector3 curpos;
2648 if(fixrot)
2649 curpos = pos + veclist[i] * netRot;
2650 else
2651 curpos = pos + veclist[i];
2419 2652
2420 if (group.IsAttachment == false && group.RootPart.Shape.State != 0) 2653 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2421 { 2654 {
@@ -2424,7 +2657,17 @@ namespace OpenSim.Region.Framework.Scenes
2424 } 2657 }
2425 2658
2426 group.FromPartID = sourcePart.UUID; 2659 group.FromPartID = sourcePart.UUID;
2427 AddNewSceneObject(group, true, curpos, rot, vel); 2660 if( i == 0)
2661 AddNewSceneObject(group, true, curpos, rot, vel);
2662 else
2663 {
2664 Quaternion crot = objlist[i].RootPart.GetWorldRotation();
2665 if (fixrot)
2666 {
2667 crot *= netRot;
2668 }
2669 AddNewSceneObject(group, true, curpos, crot, vel);
2670 }
2428 2671
2429 // We can only call this after adding the scene object, since the scene object references the scene 2672 // We can only call this after adding the scene object, since the scene object references the scene
2430 // to find out if scripts should be activated at all. 2673 // to find out if scripts should be activated at all.
@@ -2455,6 +2698,9 @@ namespace OpenSim.Region.Framework.Scenes
2455 2698
2456 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2699 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2457 { 2700 {
2701 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2702 return;
2703
2458 SceneObjectPart part = GetSceneObjectPart(objectID); 2704 SceneObjectPart part = GetSceneObjectPart(objectID);
2459 if (part == null) 2705 if (part == null)
2460 return; 2706 return;
@@ -2511,7 +2757,10 @@ namespace OpenSim.Region.Framework.Scenes
2511 } 2757 }
2512 else 2758 else
2513 { 2759 {
2514 if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)) 2760 if (!Permissions.IsGod(remoteClient.AgentId) && sog.OwnerID != remoteClient.AgentId)
2761 continue;
2762
2763 if (!Permissions.CanTransferObject(sog.UUID, groupID))
2515 continue; 2764 continue;
2516 2765
2517 if (sog.GroupID != groupID) 2766 if (sog.GroupID != groupID)
@@ -2622,7 +2871,18 @@ namespace OpenSim.Region.Framework.Scenes
2622 return; 2871 return;
2623 } 2872 }
2624 2873
2874 bool oldUsePhysics = (root.Flags & PrimFlags.Physics) != 0;
2625 m_sceneGraph.LinkObjects(root, children); 2875 m_sceneGraph.LinkObjects(root, children);
2876
2877 ScenePresence sp;
2878 if (TryGetScenePresence(agentId, out sp))
2879 {
2880 root.SendPropertiesToClient(sp.ControllingClient);
2881 if (oldUsePhysics && (root.Flags & PrimFlags.Physics) == 0)
2882 {
2883 sp.ControllingClient.SendAlertMessage("Object physics canceled");
2884 }
2885 }
2626 } 2886 }
2627 2887
2628 private string PermissionString(uint permissions) 2888 private string PermissionString(uint permissions)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 8ebcd92..34b9c5f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 /// <param name='targetID'></param> 49 /// <param name='targetID'></param>
50 /// <param name='fromAgent'></param> 50 /// <param name='fromAgent'></param>
51 /// <param name='broadcast'></param> 51 /// <param name='broadcast'></param>
52 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 52 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
53 UUID fromID, UUID targetID, bool fromAgent, bool broadcast) 53 UUID fromID, UUID targetID, bool fromAgent, bool broadcast)
54 { 54 {
55 OSChatMessage args = new OSChatMessage(); 55 OSChatMessage args = new OSChatMessage();
@@ -60,6 +60,7 @@ namespace OpenSim.Region.Framework.Scenes
60 args.Position = fromPos; 60 args.Position = fromPos;
61 args.SenderUUID = fromID; 61 args.SenderUUID = fromID;
62 args.Scene = this; 62 args.Scene = this;
63 args.Destination = targetID;
63 64
64 if (fromAgent) 65 if (fromAgent)
65 { 66 {
@@ -74,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes
74 } 75 }
75 76
76 args.From = fromName; 77 args.From = fromName;
77 args.TargetUUID = targetID; 78 //args.
78 79
79// m_log.DebugFormat( 80// m_log.DebugFormat(
80// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", 81// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}",
@@ -85,7 +86,7 @@ namespace OpenSim.Region.Framework.Scenes
85 else 86 else
86 EventManager.TriggerOnChatFromWorld(this, args); 87 EventManager.TriggerOnChatFromWorld(this, args);
87 } 88 }
88 89
89 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 90 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
90 UUID fromID, bool fromAgent, bool broadcast) 91 UUID fromID, bool fromAgent, bool broadcast)
91 { 92 {
@@ -129,19 +130,6 @@ namespace OpenSim.Region.Framework.Scenes
129 { 130 {
130 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true); 131 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true);
131 } 132 }
132 /// <summary>
133 ///
134 /// </summary>
135 /// <param name="message"></param>
136 /// <param name="type"></param>
137 /// <param name="fromPos"></param>
138 /// <param name="fromName"></param>
139 /// <param name="fromAgentID"></param>
140 /// <param name="targetID"></param>
141 public void SimChatToAgent(UUID targetID, byte[] message, Vector3 fromPos, string fromName, UUID fromID, bool fromAgent)
142 {
143 SimChat(message, ChatTypeEnum.Say, 0, fromPos, fromName, fromID, targetID, fromAgent, false);
144 }
145 133
146 /// <summary> 134 /// <summary>
147 /// 135 ///
@@ -178,27 +166,52 @@ namespace OpenSim.Region.Framework.Scenes
178 /// <param name="remoteClient"></param> 166 /// <param name="remoteClient"></param>
179 public void SelectPrim(uint primLocalID, IClientAPI remoteClient) 167 public void SelectPrim(uint primLocalID, IClientAPI remoteClient)
180 { 168 {
169 /*
170 SceneObjectPart part = GetSceneObjectPart(primLocalID);
171
172 if (null == part)
173 return;
174
175 if (part.IsRoot)
176 {
177 SceneObjectGroup sog = part.ParentGroup;
178 sog.SendPropertiesToClient(remoteClient);
179
180 // A prim is only tainted if it's allowed to be edited by the person clicking it.
181 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
182 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
183 {
184 sog.IsSelected = true;
185 EventManager.TriggerParcelPrimCountTainted();
186 }
187 }
188 else
189 {
190 part.SendPropertiesToClient(remoteClient);
191 }
192 */
181 SceneObjectPart part = GetSceneObjectPart(primLocalID); 193 SceneObjectPart part = GetSceneObjectPart(primLocalID);
182 194
183 if (null == part) 195 if (null == part)
184 return; 196 return;
185 197
186 if (part.IsRoot) 198 SceneObjectGroup sog = part.ParentGroup;
187 { 199 if (sog == null)
188 SceneObjectGroup sog = part.ParentGroup; 200 return;
189 sog.SendPropertiesToClient(remoteClient);
190 sog.IsSelected = true;
191 201
192 // A prim is only tainted if it's allowed to be edited by the person clicking it. 202 part.SendPropertiesToClient(remoteClient);
193 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 203
194 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 204 // waste of time because properties do not send prim flags as they should
195 { 205 // if a friend got or lost edit rights after login, a full update is needed
196 EventManager.TriggerParcelPrimCountTainted(); 206 if(sog.OwnerID != remoteClient.AgentId)
197 } 207 part.SendFullUpdate(remoteClient);
198 } 208
199 else 209 // A prim is only tainted if it's allowed to be edited by the person clicking it.
210 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
211 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
200 { 212 {
201 part.SendPropertiesToClient(remoteClient); 213 part.IsSelected = true;
214 EventManager.TriggerParcelPrimCountTainted();
202 } 215 }
203 } 216 }
204 217
@@ -251,7 +264,7 @@ namespace OpenSim.Region.Framework.Scenes
251 SceneObjectPart part = GetSceneObjectPart(primLocalID); 264 SceneObjectPart part = GetSceneObjectPart(primLocalID);
252 if (part == null) 265 if (part == null)
253 return; 266 return;
254 267 /*
255 // A deselect packet contains all the local prims being deselected. However, since selection is still 268 // A deselect packet contains all the local prims being deselected. However, since selection is still
256 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims 269 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims
257 // we end up sending many duplicate ObjectUpdates 270 // we end up sending many duplicate ObjectUpdates
@@ -262,7 +275,9 @@ namespace OpenSim.Region.Framework.Scenes
262 // handled by group, but by prim. Legacy cruft. 275 // handled by group, but by prim. Legacy cruft.
263 // TODO: Make selection flagging per prim! 276 // TODO: Make selection flagging per prim!
264 // 277 //
265 part.ParentGroup.IsSelected = false; 278 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
279 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
280 part.ParentGroup.IsSelected = false;
266 281
267 part.ParentGroup.ScheduleGroupForFullUpdate(); 282 part.ParentGroup.ScheduleGroupForFullUpdate();
268 283
@@ -279,6 +294,25 @@ namespace OpenSim.Region.Framework.Scenes
279 part.UUID, remoteClient.AgentId)) 294 part.UUID, remoteClient.AgentId))
280 EventManager.TriggerParcelPrimCountTainted(); 295 EventManager.TriggerParcelPrimCountTainted();
281 } 296 }
297 */
298
299 bool oldgprSelect = part.ParentGroup.IsSelected;
300
301 // This is wrong, wrong, wrong. Selection should not be
302 // handled by group, but by prim. Legacy cruft.
303 // TODO: Make selection flagging per prim!
304 //
305 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
306 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
307 {
308 part.IsSelected = false;
309 if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected)
310 EventManager.TriggerParcelPrimCountTainted();
311
312 // restore targetOmega
313 if (part.AngularVelocity != Vector3.Zero)
314 part.ScheduleTerseUpdate();
315 }
282 } 316 }
283 317
284 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, 318 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,
@@ -433,12 +467,26 @@ namespace OpenSim.Region.Framework.Scenes
433 } 467 }
434 }); 468 });
435 } 469 }
436 470
437 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other) 471 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other)
438 { 472 {
439 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10; 473 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
440 } 474 }
441 475
476 private class DescendentsRequestData
477 {
478 public IClientAPI RemoteClient;
479 public UUID FolderID;
480 public UUID OwnerID;
481 public bool FetchFolders;
482 public bool FetchItems;
483 public int SortOrder;
484 }
485
486 private Queue<DescendentsRequestData> m_descendentsRequestQueue = new Queue<DescendentsRequestData>();
487 private Object m_descendentsRequestLock = new Object();
488 private bool m_descendentsRequestProcessing = false;
489
442 /// <summary> 490 /// <summary>
443 /// Tell the client about the various child items and folders contained in the requested folder. 491 /// Tell the client about the various child items and folders contained in the requested folder.
444 /// </summary> 492 /// </summary>
@@ -475,11 +523,31 @@ namespace OpenSim.Region.Framework.Scenes
475 } 523 }
476 } 524 }
477 525
478 // We're going to send the reply async, because there may be 526 lock (m_descendentsRequestLock)
479 // an enormous quantity of packets -- basically the entire inventory! 527 {
480 // We don't want to block the client thread while all that is happening. 528 if (!m_descendentsRequestProcessing)
481 SendInventoryDelegate d = SendInventoryAsync; 529 {
482 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); 530 m_descendentsRequestProcessing = true;
531
532 // We're going to send the reply async, because there may be
533 // an enormous quantity of packets -- basically the entire inventory!
534 // We don't want to block the client thread while all that is happening.
535 SendInventoryDelegate d = SendInventoryAsync;
536 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d);
537
538 return;
539 }
540
541 DescendentsRequestData req = new DescendentsRequestData();
542 req.RemoteClient = remoteClient;
543 req.FolderID = folderID;
544 req.OwnerID = ownerID;
545 req.FetchFolders = fetchFolders;
546 req.FetchItems = fetchItems;
547 req.SortOrder = sortOrder;
548
549 m_descendentsRequestQueue.Enqueue(req);
550 }
483 } 551 }
484 552
485 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); 553 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder);
@@ -496,12 +564,28 @@ namespace OpenSim.Region.Framework.Scenes
496 string.Format( 564 string.Format(
497 "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e)); 565 "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e));
498 } 566 }
567 Thread.Sleep(20);
499 } 568 }
500 569
501 void SendInventoryComplete(IAsyncResult iar) 570 void SendInventoryComplete(IAsyncResult iar)
502 { 571 {
503 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState; 572 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState;
504 d.EndInvoke(iar); 573 d.EndInvoke(iar);
574
575 lock (m_descendentsRequestLock)
576 {
577 if (m_descendentsRequestQueue.Count > 0)
578 {
579 DescendentsRequestData req = m_descendentsRequestQueue.Dequeue();
580
581 d = SendInventoryAsync;
582 d.BeginInvoke(req.RemoteClient, req.FolderID, req.OwnerID, req.FetchFolders, req.FetchItems, req.SortOrder, SendInventoryComplete, d);
583
584 return;
585 }
586
587 m_descendentsRequestProcessing = false;
588 }
505 } 589 }
506 590
507 /// <summary> 591 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index 535d87a..4d90726 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes
70 public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene); 70 public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene);
71 public delegate bool IsAdministratorHandler(UUID user); 71 public delegate bool IsAdministratorHandler(UUID user);
72 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene); 72 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene);
73 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene); 73 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene, bool allowManager);
74 public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene); 74 public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene);
75 public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene); 75 public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene);
76 public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene); 76 public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene);
@@ -763,7 +763,7 @@ namespace OpenSim.Region.Framework.Scenes
763 763
764 #region EDIT PARCEL 764 #region EDIT PARCEL
765 765
766 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p) 766 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, bool allowManager)
767 { 767 {
768 EditParcelPropertiesHandler handler = OnEditParcelProperties; 768 EditParcelPropertiesHandler handler = OnEditParcelProperties;
769 if (handler != null) 769 if (handler != null)
@@ -771,7 +771,7 @@ namespace OpenSim.Region.Framework.Scenes
771 Delegate[] list = handler.GetInvocationList(); 771 Delegate[] list = handler.GetInvocationList();
772 foreach (EditParcelPropertiesHandler h in list) 772 foreach (EditParcelPropertiesHandler h in list)
773 { 773 {
774 if (h(user, parcel, p, m_scene) == false) 774 if (h(user, parcel, p, m_scene, allowManager) == false)
775 return false; 775 return false;
776 } 776 }
777 } 777 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 2fe6e22..2fcb78d 100755
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -61,8 +61,7 @@ namespace OpenSim.Region.Framework.Scenes
61 { 61 {
62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; 62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L;
63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; 63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L;
64 64
65 public const int m_defaultNumberFramesStored = 10;
66 65
67 public delegate void SynchronizeSceneHandler(Scene scene); 66 public delegate void SynchronizeSceneHandler(Scene scene);
68 67
@@ -105,9 +104,10 @@ namespace OpenSim.Region.Framework.Scenes
105 /// <summary> 104 /// <summary>
106 /// If false then physical objects are disabled, though collisions will continue as normal. 105 /// If false then physical objects are disabled, though collisions will continue as normal.
107 /// </summary> 106 /// </summary>
108 public bool PhysicsEnabled 107
109 { 108 public bool PhysicsEnabled
110 get 109 {
110 get
111 { 111 {
112 return m_physicsEnabled; 112 return m_physicsEnabled;
113 } 113 }
@@ -216,7 +216,7 @@ namespace OpenSim.Region.Framework.Scenes
216 /// <summary> 216 /// <summary>
217 /// Maximum value of the size of a physical prim in each axis 217 /// Maximum value of the size of a physical prim in each axis
218 /// </summary> 218 /// </summary>
219 public float m_maxPhys = 64; 219 public float m_maxPhys = 10;
220 220
221 /// <summary> 221 /// <summary>
222 /// Max prims an object will hold 222 /// Max prims an object will hold
@@ -228,10 +228,16 @@ namespace OpenSim.Region.Framework.Scenes
228 public bool m_allowScriptCrossings = true; 228 public bool m_allowScriptCrossings = true;
229 229
230 /// <summary> 230 /// <summary>
231
231 /// Can avatars cross from and to this region? 232 /// Can avatars cross from and to this region?
232 /// </summary> 233 /// </summary>
233 public bool AllowAvatarCrossing { get; set; } 234 public bool AllowAvatarCrossing { get; set; }
234 235
236 /// Max prims an Physical object will hold
237 /// </summary>
238 ///
239 public int m_linksetPhysCapacity = 0;
240
235 public bool m_useFlySlow; 241 public bool m_useFlySlow;
236 public bool m_useTrashOnDelete = true; 242 public bool m_useTrashOnDelete = true;
237 243
@@ -265,20 +271,17 @@ namespace OpenSim.Region.Framework.Scenes
265 /// </summary> 271 /// </summary>
266 public int ChildTerseUpdatePeriod { get; set; } 272 public int ChildTerseUpdatePeriod { get; set; }
267 273
268 protected float m_defaultDrawDistance = 255.0f; 274 protected float m_defaultDrawDistance = 255f;
269 public float DefaultDrawDistance 275 public float DefaultDrawDistance
270 { 276 {
271 // get { return m_defaultDrawDistance; } 277 get { return m_defaultDrawDistance; }
272 get 278 }
273 {
274 if (RegionInfo != null)
275 {
276 float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
277 m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension);
278 279
279 } 280 protected float m_maxDrawDistance = 512.0f;
280 return m_defaultDrawDistance; 281// protected float m_maxDrawDistance = 256.0f;
281 } 282 public float MaxDrawDistance
283 {
284 get { return m_maxDrawDistance; }
282 } 285 }
283 286
284 private List<string> m_AllowedViewers = new List<string>(); 287 private List<string> m_AllowedViewers = new List<string>();
@@ -287,8 +290,8 @@ namespace OpenSim.Region.Framework.Scenes
287 // TODO: need to figure out how allow client agents but deny 290 // TODO: need to figure out how allow client agents but deny
288 // root agents when ACL denies access to root agent 291 // root agents when ACL denies access to root agent
289 public bool m_strictAccessControl = true; 292 public bool m_strictAccessControl = true;
290 293 public bool m_seeIntoBannedRegion = false;
291 public int MaxUndoCount { get; set; } 294 public int MaxUndoCount = 5;
292 295
293 public bool SeeIntoRegion { get; set; } 296 public bool SeeIntoRegion { get; set; }
294 297
@@ -306,11 +309,13 @@ namespace OpenSim.Region.Framework.Scenes
306 309
307 protected int m_splitRegionID; 310 protected int m_splitRegionID;
308 protected Timer m_restartWaitTimer = new Timer(); 311 protected Timer m_restartWaitTimer = new Timer();
312 protected Timer m_timerWatchdog = new Timer();
309 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 313 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
310 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 314 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
311 protected string m_simulatorVersion = "OpenSimulator Server"; 315 protected string m_simulatorVersion = "OpenSimulator Server";
312 protected AgentCircuitManager m_authenticateHandler; 316 protected AgentCircuitManager m_authenticateHandler;
313 protected SceneCommunicationService m_sceneGridService; 317 protected SceneCommunicationService m_sceneGridService;
318 protected ISnmpModule m_snmpService = null;
314 319
315 protected ISimulationDataService m_SimulationDataService; 320 protected ISimulationDataService m_SimulationDataService;
316 protected IEstateDataService m_EstateDataService; 321 protected IEstateDataService m_EstateDataService;
@@ -339,17 +344,6 @@ namespace OpenSim.Region.Framework.Scenes
339 private Dictionary<string, string> m_extraSettings; 344 private Dictionary<string, string> m_extraSettings;
340 345
341 /// <summary> 346 /// <summary>
342 /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer
343 /// rather than on a single thread that sleeps.
344 /// </summary>
345 public bool UpdateOnTimer { get; set; }
346
347 /// <summary>
348 /// Only used if we are updating scene on a timer rather than sleeping a thread.
349 /// </summary>
350 private Timer m_sceneUpdateTimer;
351
352 /// <summary>
353 /// Current scene frame number 347 /// Current scene frame number
354 /// </summary> 348 /// </summary>
355 public uint Frame 349 public uint Frame
@@ -364,24 +358,9 @@ namespace OpenSim.Region.Framework.Scenes
364 public uint MaintenanceRun { get; private set; } 358 public uint MaintenanceRun { get; private set; }
365 359
366 /// <summary> 360 /// <summary>
367 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we 361 /// Frame time
368 /// will sleep for the remaining period.
369 /// </summary>
370 /// <remarks>
371 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
372 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
373 /// </remarks> 362 /// </remarks>
374 public int MinFrameTicks 363 public float FrameTime { get; private set; }
375 {
376 get { return m_minFrameTicks; }
377 private set
378 {
379 m_minFrameTicks = value;
380 MinFrameSeconds = (float)m_minFrameTicks / 1000;
381 }
382 }
383 private int m_minFrameTicks;
384
385 public int FrameTimeWarnPercent { get; private set; } 364 public int FrameTimeWarnPercent { get; private set; }
386 public int FrameTimeCritPercent { get; private set; } 365 public int FrameTimeCritPercent { get; private set; }
387 366
@@ -395,17 +374,7 @@ namespace OpenSim.Region.Framework.Scenes
395 /// <remarks> 374 /// <remarks>
396 /// Always derived from MinFrameTicks. 375 /// Always derived from MinFrameTicks.
397 /// </remarks> 376 /// </remarks>
398 public float MinFrameSeconds { get; private set; } 377 public float MinMaintenanceTime { get; private set; }
399
400 /// <summary>
401 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we
402 /// will sleep for the remaining period.
403 /// </summary>
404 /// <remarks>
405 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
406 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
407 /// </remarks>
408 public int MinMaintenanceTicks { get; set; }
409 378
410 private int m_update_physics = 1; 379 private int m_update_physics = 1;
411 private int m_update_entitymovement = 1; 380 private int m_update_entitymovement = 1;
@@ -413,22 +382,23 @@ namespace OpenSim.Region.Framework.Scenes
413 private int m_update_presences = 1; // Update scene presence movements 382 private int m_update_presences = 1; // Update scene presence movements
414 private int m_update_events = 1; 383 private int m_update_events = 1;
415 private int m_update_backup = 200; 384 private int m_update_backup = 200;
416 private int m_update_terrain = 50; 385
417 // private int m_update_land = 1; 386 private int m_update_terrain = 1000;
387 private int m_update_land = 10;
388
418 private int m_update_coarse_locations = 50; 389 private int m_update_coarse_locations = 50;
419 private int m_update_temp_cleaning = 180; 390 private int m_update_temp_cleaning = 180;
420 391
421 private int agentMS; 392 private float agentMS;
422 private int frameMS; 393 private float frameMS;
423 private int physicsMS2; 394 private float physicsMS2;
424 private int physicsMS; 395 private float physicsMS;
425 private int otherMS; 396 private float otherMS;
426 private int tempOnRezMS; 397 private float tempOnRezMS;
427 private int eventMS; 398 private float eventMS;
428 private int backupMS; 399 private float backupMS;
429 private int terrainMS; 400 private float terrainMS;
430 private int landMS; 401 private float landMS;
431 private int spareMS;
432 402
433 // A temporary configuration flag to enable using FireAndForget to process 403 // A temporary configuration flag to enable using FireAndForget to process
434 // collisions from the physics engine. There is a problem with collisions 404 // collisions from the physics engine. There is a problem with collisions
@@ -446,6 +416,7 @@ namespace OpenSim.Region.Framework.Scenes
446 /// </summary> 416 /// </summary>
447 private int m_lastFrameTick; 417 private int m_lastFrameTick;
448 418
419 public bool CombineRegions = false;
449 /// <summary> 420 /// <summary>
450 /// Tick at which the last maintenance run occurred. 421 /// Tick at which the last maintenance run occurred.
451 /// </summary> 422 /// </summary>
@@ -477,7 +448,7 @@ namespace OpenSim.Region.Framework.Scenes
477 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 448 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
478 private volatile bool m_backingup; 449 private volatile bool m_backingup;
479 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 450 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
480 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); 451 private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>();
481 452
482 private string m_defaultScriptEngine; 453 private string m_defaultScriptEngine;
483 454
@@ -492,6 +463,11 @@ namespace OpenSim.Region.Framework.Scenes
492 /// </summary> 463 /// </summary>
493 private int m_LastLogin; 464 private int m_LastLogin;
494 465
466 private int m_lastIncoming;
467 private int m_lastOutgoing;
468 private int m_hbRestarts = 0;
469
470
495 /// <summary> 471 /// <summary>
496 /// Thread that runs the scene loop. 472 /// Thread that runs the scene loop.
497 /// </summary> 473 /// </summary>
@@ -540,6 +516,16 @@ namespace OpenSim.Region.Framework.Scenes
540 public bool IsRunning { get { return m_isRunning; } } 516 public bool IsRunning { get { return m_isRunning; } }
541 private volatile bool m_isRunning; 517 private volatile bool m_isRunning;
542 518
519// private int m_lastUpdate;
520 private bool m_firstHeartbeat = true;
521
522 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
523 private bool m_reprioritizationEnabled = true;
524 private double m_reprioritizationInterval = 5000.0;
525 private double m_rootReprioritizationDistance = 10.0;
526 private double m_childReprioritizationDistance = 20.0;
527
528
543 private Timer m_mapGenerationTimer = new Timer(); 529 private Timer m_mapGenerationTimer = new Timer();
544 private bool m_generateMaptiles; 530 private bool m_generateMaptiles;
545 531
@@ -571,6 +557,19 @@ namespace OpenSim.Region.Framework.Scenes
571 get { return m_sceneGridService; } 557 get { return m_sceneGridService; }
572 } 558 }
573 559
560 public ISnmpModule SnmpService
561 {
562 get
563 {
564 if (m_snmpService == null)
565 {
566 m_snmpService = RequestModuleInterface<ISnmpModule>();
567 }
568
569 return m_snmpService;
570 }
571 }
572
574 public ISimulationDataService SimulationDataService 573 public ISimulationDataService SimulationDataService
575 { 574 {
576 get 575 get
@@ -777,15 +776,15 @@ namespace OpenSim.Region.Framework.Scenes
777 get { return m_capsModule; } 776 get { return m_capsModule; }
778 } 777 }
779 778
780 public int MonitorFrameTime { get { return frameMS; } } 779 public int MonitorFrameTime { get { return (int)frameMS; } }
781 public int MonitorPhysicsUpdateTime { get { return physicsMS; } } 780 public int MonitorPhysicsUpdateTime { get { return (int)physicsMS; } }
782 public int MonitorPhysicsSyncTime { get { return physicsMS2; } } 781 public int MonitorPhysicsSyncTime { get { return (int)physicsMS2; } }
783 public int MonitorOtherTime { get { return otherMS; } } 782 public int MonitorOtherTime { get { return (int)otherMS; } }
784 public int MonitorTempOnRezTime { get { return tempOnRezMS; } } 783 public int MonitorTempOnRezTime { get { return (int)tempOnRezMS; } }
785 public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? 784 public int MonitorEventTime { get { return (int)eventMS; } } // This may need to be divided into each event?
786 public int MonitorBackupTime { get { return backupMS; } } 785 public int MonitorBackupTime { get { return (int)backupMS; } }
787 public int MonitorTerrainTime { get { return terrainMS; } } 786 public int MonitorTerrainTime { get { return (int)terrainMS; } }
788 public int MonitorLandTime { get { return landMS; } } 787 public int MonitorLandTime { get { return (int)landMS; } }
789 public int MonitorLastFrameTick { get { return m_lastFrameTick; } } 788 public int MonitorLastFrameTick { get { return m_lastFrameTick; } }
790 789
791 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } 790 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; }
@@ -863,11 +862,11 @@ namespace OpenSim.Region.Framework.Scenes
863 : this(regInfo) 862 : this(regInfo)
864 { 863 {
865 m_config = config; 864 m_config = config;
866 MinFrameTicks = 89; 865 FrameTime = 0.0908f;
867 FrameTimeWarnPercent = 60; 866 FrameTimeWarnPercent = 60;
868 FrameTimeCritPercent = 40; 867 FrameTimeCritPercent = 40;
869 Normalized55FPS = true; 868 Normalized55FPS = true;
870 MinMaintenanceTicks = 1000; 869 MinMaintenanceTime = 1;
871 SeeIntoRegion = true; 870 SeeIntoRegion = true;
872 871
873 Random random = new Random(); 872 Random random = new Random();
@@ -878,6 +877,9 @@ namespace OpenSim.Region.Framework.Scenes
878 m_SimulationDataService = simDataService; 877 m_SimulationDataService = simDataService;
879 m_EstateDataService = estateDataService; 878 m_EstateDataService = estateDataService;
880 879
880 m_lastIncoming = 0;
881 m_lastOutgoing = 0;
882
881 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 883 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
882 m_asyncSceneObjectDeleter.Enabled = true; 884 m_asyncSceneObjectDeleter.Enabled = true;
883 885
@@ -935,7 +937,7 @@ namespace OpenSim.Region.Framework.Scenes
935 EventManager.OnLandObjectRemoved += 937 EventManager.OnLandObjectRemoved +=
936 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 938 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
937 939
938 RegisterDefaultSceneEvents(); 940 RegisterDefaultSceneEvents();
939 941
940 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled 942 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled
941 // better in the future. 943 // better in the future.
@@ -956,6 +958,11 @@ namespace OpenSim.Region.Framework.Scenes
956 StartDisabled = startupConfig.GetBoolean("StartDisabled", false); 958 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
957 959
958 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); 960 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
961 m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance);
962
963 if (m_defaultDrawDistance > m_maxDrawDistance)
964 m_defaultDrawDistance = m_maxDrawDistance;
965
959 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); 966 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
960 if (!UseBackup) 967 if (!UseBackup)
961 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 968 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
@@ -967,9 +974,8 @@ namespace OpenSim.Region.Framework.Scenes
967 974
968 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); 975 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
969 976
970 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); 977 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
971 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); 978 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
972
973 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 979 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
974 if (RegionInfo.NonphysPrimMin > 0) 980 if (RegionInfo.NonphysPrimMin > 0)
975 { 981 {
@@ -989,11 +995,24 @@ namespace OpenSim.Region.Framework.Scenes
989 } 995 }
990 996
991 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 997 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
998
992 if (RegionInfo.PhysPrimMax > 0) 999 if (RegionInfo.PhysPrimMax > 0)
993 { 1000 {
994 m_maxPhys = RegionInfo.PhysPrimMax; 1001 m_maxPhys = RegionInfo.PhysPrimMax;
995 } 1002 }
996 1003
1004 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
1005 if (RegionInfo.LinksetCapacity > 0)
1006 {
1007 m_linksetCapacity = RegionInfo.LinksetCapacity;
1008 }
1009
1010 m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity);
1011
1012
1013 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1014 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1015
997 // Here, if clamping is requested in either global or 1016 // Here, if clamping is requested in either global or
998 // local config, it will be used 1017 // local config, it will be used
999 // 1018 //
@@ -1003,13 +1022,7 @@ namespace OpenSim.Region.Framework.Scenes
1003 m_clampPrimSize = true; 1022 m_clampPrimSize = true;
1004 } 1023 }
1005 1024
1006 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); 1025 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
1007 if (RegionInfo.LinksetCapacity > 0)
1008 {
1009 m_linksetCapacity = RegionInfo.LinksetCapacity;
1010 }
1011
1012 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete);
1013 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 1026 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
1014 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 1027 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
1015 m_dontPersistBefore = 1028 m_dontPersistBefore =
@@ -1020,11 +1033,11 @@ namespace OpenSim.Region.Framework.Scenes
1020 m_persistAfter *= 10000000; 1033 m_persistAfter *= 10000000;
1021 1034
1022 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 1035 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
1023 1036 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
1024 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1025 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1026 1037
1027 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 1038 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
1039 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
1040 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
1028 1041
1029 string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; 1042 string[] possibleMapConfigSections = new string[] { "Map", "Startup" };
1030 1043
@@ -1070,7 +1083,7 @@ namespace OpenSim.Region.Framework.Scenes
1070 1083
1071 if (grant.Length > 0) 1084 if (grant.Length > 0)
1072 { 1085 {
1073 foreach (string viewer in grant.Split('|')) 1086 foreach (string viewer in grant.Split(','))
1074 { 1087 {
1075 m_AllowedViewers.Add(viewer.Trim().ToLower()); 1088 m_AllowedViewers.Add(viewer.Trim().ToLower());
1076 } 1089 }
@@ -1086,17 +1099,16 @@ namespace OpenSim.Region.Framework.Scenes
1086 1099
1087 if (grant.Length > 0) 1100 if (grant.Length > 0)
1088 { 1101 {
1089 foreach (string viewer in grant.Split('|')) 1102 foreach (string viewer in grant.Split(','))
1090 { 1103 {
1091 m_BannedViewers.Add(viewer.Trim().ToLower()); 1104 m_BannedViewers.Add(viewer.Trim().ToLower());
1092 } 1105 }
1093 } 1106 }
1094 1107
1095 if (startupConfig.Contains("MinFrameTime")) 1108 FrameTime = startupConfig.GetFloat( "FrameTime", FrameTime);
1096 MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000);
1097 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent); 1109 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent);
1098 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent); 1110 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent);
1099 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS); 1111 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS);
1100 1112
1101 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); 1113 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup);
1102 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 1114 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
@@ -1174,39 +1186,12 @@ namespace OpenSim.Region.Framework.Scenes
1174 1186
1175 #endregion Interest Management 1187 #endregion Interest Management
1176 1188
1177 // The timer used by the Stopwatch class depends on the system hardware and operating system; inform
1178 // if the timer is based on a high-resolution performance counter or based on the system timer;
1179 // the performance counter will provide a more precise time than the system timer
1180 if (Stopwatch.IsHighResolution)
1181 m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics.");
1182 else
1183 m_log.InfoFormat("[SCENE]: Using system timer for statistics.");
1184 1189
1185 // Acquire the statistics section of the OpenSim.ini file located 1190 StatsReporter = new SimStatsReporter(this);
1186 // in the bin directory
1187 IConfig statisticsConfig = m_config.Configs["Statistics"];
1188
1189 // Confirm that the statistics section existed in the configuration
1190 // file
1191 if (statisticsConfig != null)
1192 {
1193 // Create the StatsReporter using the number of frames to store
1194 // for the frame time statistics, or 10 frames if the config
1195 // file doesn't contain a value
1196 StatsReporter = new SimStatsReporter(this,
1197 statisticsConfig.GetInt("NumberOfFrames",
1198 m_defaultNumberFramesStored));
1199 }
1200 else
1201 {
1202 // Create a StatsReporter with the current scene and a default
1203 // 10 frames stored for the frame time statistics
1204 StatsReporter = new SimStatsReporter(this);
1205 }
1206 1191
1207 StatsReporter.OnSendStatsResult += SendSimStatsPackets; 1192 StatsReporter.OnSendStatsResult += SendSimStatsPackets;
1208 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; 1193 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
1209 1194
1210 } 1195 }
1211 1196
1212 public Scene(RegionInfo regInfo) 1197 public Scene(RegionInfo regInfo)
@@ -1249,6 +1234,7 @@ namespace OpenSim.Region.Framework.Scenes
1249 m_eventManager = new EventManager(); 1234 m_eventManager = new EventManager();
1250 1235
1251 m_permissions = new ScenePermissions(this); 1236 m_permissions = new ScenePermissions(this);
1237
1252 } 1238 }
1253 1239
1254 #endregion 1240 #endregion
@@ -1285,7 +1271,6 @@ namespace OpenSim.Region.Framework.Scenes
1285 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras)) 1271 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras))
1286 openSimExtras = new OSDMap(); 1272 openSimExtras = new OSDMap();
1287 1273
1288 float FrameTime = MinFrameTicks / 1000.0f;
1289 float statisticsFPSfactor = 1.0f; 1274 float statisticsFPSfactor = 1.0f;
1290 if(Normalized55FPS) 1275 if(Normalized55FPS)
1291 statisticsFPSfactor = 55.0f * FrameTime; 1276 statisticsFPSfactor = 55.0f * FrameTime;
@@ -1325,20 +1310,8 @@ namespace OpenSim.Region.Framework.Scenes
1325 { 1310 {
1326 if (RegionInfo.RegionHandle != otherRegion.RegionHandle) 1311 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
1327 { 1312 {
1328 //// If these are cast to INT because long + negative values + abs returns invalid data
1329 //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX);
1330 //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY);
1331 //if (resultX <= 1 && resultY <= 1)
1332 float dist = (float)Math.Max(DefaultDrawDistance,
1333 (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY));
1334 uint newRegionX, newRegionY, thisRegionX, thisRegionY;
1335 Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY);
1336 Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY);
1337 1313
1338 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1314 if (isNeighborRegion(otherRegion))
1339 // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY);
1340
1341 if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY))
1342 { 1315 {
1343 // Let the grid service module know, so this can be cached 1316 // Let the grid service module know, so this can be cached
1344 m_eventManager.TriggerOnRegionUp(otherRegion); 1317 m_eventManager.TriggerOnRegionUp(otherRegion);
@@ -1373,6 +1346,21 @@ namespace OpenSim.Region.Framework.Scenes
1373 } 1346 }
1374 } 1347 }
1375 1348
1349 public bool isNeighborRegion(GridRegion otherRegion)
1350 {
1351 int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; ;
1352
1353 if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX)
1354 return false;
1355
1356 tmp = otherRegion.RegionLocY - (int)RegionInfo.WorldLocY;
1357
1358 if (tmp < -otherRegion.RegionSizeY && tmp > RegionInfo.RegionSizeY)
1359 return false;
1360
1361 return true;
1362 }
1363
1376 public void AddNeighborRegion(RegionInfo region) 1364 public void AddNeighborRegion(RegionInfo region)
1377 { 1365 {
1378 lock (m_neighbours) 1366 lock (m_neighbours)
@@ -1504,8 +1492,11 @@ namespace OpenSim.Region.Framework.Scenes
1504 // Stop all client threads. 1492 // Stop all client threads.
1505 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); 1493 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1506 1494
1507 m_log.Debug("[SCENE]: Persisting changed objects"); 1495 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1508 EventManager.TriggerSceneShuttingDown(this); 1496 EventManager.TriggerSceneShuttingDown(this);
1497
1498 m_log.Debug("[SCENE]: Persisting changed objects");
1499
1509 Backup(false); 1500 Backup(false);
1510 m_sceneGraph.Close(); 1501 m_sceneGraph.Close();
1511 1502
@@ -1519,6 +1510,7 @@ namespace OpenSim.Region.Framework.Scenes
1519 // attempt to reference a null or disposed physics scene. 1510 // attempt to reference a null or disposed physics scene.
1520 if (PhysicsScene != null) 1511 if (PhysicsScene != null)
1521 { 1512 {
1513 m_log.Debug("[SCENE]: Dispose Physics");
1522 PhysicsScene phys = PhysicsScene; 1514 PhysicsScene phys = PhysicsScene;
1523 // remove the physics engine from both Scene and SceneGraph 1515 // remove the physics engine from both Scene and SceneGraph
1524 PhysicsScene = null; 1516 PhysicsScene = null;
@@ -1550,10 +1542,28 @@ namespace OpenSim.Region.Framework.Scenes
1550// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1542// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1551 if (m_heartbeatThread != null) 1543 if (m_heartbeatThread != null)
1552 { 1544 {
1545 m_hbRestarts++;
1546 if(m_hbRestarts > 10)
1547 Environment.Exit(1);
1548 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1549
1550//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1551//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1552//proc.EnableRaisingEvents=false;
1553//proc.StartInfo.FileName = "/bin/kill";
1554//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1555//proc.Start();
1556//proc.WaitForExit();
1557//Thread.Sleep(1000);
1558//Environment.Exit(1);
1553 m_heartbeatThread.Abort(); 1559 m_heartbeatThread.Abort();
1560 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1554 m_heartbeatThread = null; 1561 m_heartbeatThread = null;
1555 } 1562 }
1556 1563
1564 // tell physics to finish building actor
1565 m_sceneGraph.ProcessPhysicsPreSimulation();
1566
1557 m_heartbeatThread 1567 m_heartbeatThread
1558 = WorkManager.StartThread( 1568 = WorkManager.StartThread(
1559 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); 1569 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false);
@@ -1601,45 +1611,8 @@ namespace OpenSim.Region.Framework.Scenes
1601 1611
1602 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1612 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1603 m_lastFrameTick = Util.EnvironmentTickCount(); 1613 m_lastFrameTick = Util.EnvironmentTickCount();
1604 1614 Update(-1);
1605 if (UpdateOnTimer) 1615 }
1606 {
1607 m_sceneUpdateTimer = new Timer(MinFrameTicks);
1608 m_sceneUpdateTimer.AutoReset = true;
1609 m_sceneUpdateTimer.Elapsed += Update;
1610 m_sceneUpdateTimer.Start();
1611 }
1612 else
1613 {
1614 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1615 Update(-1);
1616 Watchdog.RemoveThread();
1617 m_isRunning = false;
1618 }
1619 }
1620
1621 private volatile bool m_isTimerUpdateRunning;
1622
1623 private void Update(object sender, ElapsedEventArgs e)
1624 {
1625 if (m_isTimerUpdateRunning)
1626 return;
1627
1628 m_isTimerUpdateRunning = true;
1629
1630 // If the last frame did not complete on time, then immediately start the next update on the same thread
1631 // and ignore further timed updates until we have a frame that had spare time.
1632 while (!Update(1) && Active) { }
1633
1634 if (!Active || m_shuttingDown)
1635 {
1636 m_sceneUpdateTimer.Stop();
1637 m_sceneUpdateTimer = null;
1638 m_isRunning = false;
1639 }
1640
1641 m_isTimerUpdateRunning = false;
1642 }
1643 1616
1644 private void Maintenance() 1617 private void Maintenance()
1645 { 1618 {
@@ -1708,24 +1681,24 @@ namespace OpenSim.Region.Framework.Scenes
1708 previousMaintenanceTick = m_lastMaintenanceTick; 1681 previousMaintenanceTick = m_lastMaintenanceTick;
1709 m_lastMaintenanceTick = Util.EnvironmentTickCount(); 1682 m_lastMaintenanceTick = Util.EnvironmentTickCount();
1710 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); 1683 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc);
1711 runtc = MinMaintenanceTicks - runtc; 1684 runtc = (int)(MinMaintenanceTime * 1000) - runtc;
1712 1685
1713 if (runtc > 0) 1686 if (runtc > 0)
1714 m_maintenanceWaitEvent.WaitOne(runtc); 1687 m_maintenanceWaitEvent.WaitOne(runtc);
1715 1688
1716 // Optionally warn if a frame takes double the amount of time that it should. 1689 // Optionally warn if a frame takes double the amount of time that it should.
1717 if (DebugUpdates 1690 if (DebugUpdates
1718 && Util.EnvironmentTickCountSubtract( 1691 && Util.EnvironmentTickCountSubtract(
1719 m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2) 1692 m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2))
1720 m_log.WarnFormat( 1693 m_log.WarnFormat(
1721 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", 1694 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}",
1722 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), 1695 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick),
1723 MinMaintenanceTicks, 1696 MinMaintenanceTime * 1000,
1724 RegionInfo.RegionName); 1697 RegionInfo.RegionName);
1725 } 1698 }
1726 } 1699 }
1727 1700
1728 public override bool Update(int frames) 1701 public override void Update(int frames)
1729 { 1702 {
1730 long? endFrame = null; 1703 long? endFrame = null;
1731 1704
@@ -1733,119 +1706,78 @@ namespace OpenSim.Region.Framework.Scenes
1733 endFrame = Frame + frames; 1706 endFrame = Frame + frames;
1734 1707
1735 float physicsFPS = 0f; 1708 float physicsFPS = 0f;
1736 int previousFrameTick, tmpMS; 1709 float frameTimeMS = FrameTime * 1000.0f;
1737 1710
1738 // These variables will be used to save the precise frame time using the 1711 int previousFrameTick;
1739 // Stopwatch class of Microsoft SDK; the times are recorded at the start 1712
1740 // and end of a particular section of code, and then used to calculate 1713 double tmpMS;
1741 // the frame times, which are the sums of the sections for each given name 1714 double tmpMS2;
1742 double preciseTotalFrameTime = 0.0; 1715 double framestart;
1743 double preciseSimFrameTime = 0.0; 1716 float sleepMS;
1744 double precisePhysicsFrameTime = 0.0; 1717 float sleepError = 0;
1745 Stopwatch totalFrameStopwatch = new Stopwatch();
1746 Stopwatch simFrameStopwatch = new Stopwatch();
1747 Stopwatch physicsFrameStopwatch = new Stopwatch();
1748
1749 // Begin the stopwatch to keep track of the time that the frame
1750 // started running to determine how long the frame took to complete
1751 totalFrameStopwatch.Start();
1752 1718
1753 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1719 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1754 { 1720 {
1721 framestart = Util.GetTimeStampMS();
1755 ++Frame; 1722 ++Frame;
1756 1723
1757 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1724 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1758 1725
1759 agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; 1726 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0f;
1760 1727
1761 try 1728 try
1762 { 1729 {
1763 EventManager.TriggerRegionHeartbeatStart(this); 1730 EventManager.TriggerRegionHeartbeatStart(this);
1764 1731
1765 // Apply taints in terrain module to terrain in physics scene 1732 // Apply taints in terrain module to terrain in physics scene
1733
1734 tmpMS = Util.GetTimeStampMS();
1735
1736 if (Frame % 4 == 0)
1737 {
1738 CheckTerrainUpdates();
1739 }
1740
1766 if (Frame % m_update_terrain == 0) 1741 if (Frame % m_update_terrain == 0)
1767 { 1742 {
1768 // At several points inside the code there was a need to
1769 // create a more precise measurement of time elapsed.
1770 // This led to the addition of variables that have a
1771 // similar function and thus remain tightly connected to
1772 // their original counterparts. However, the original
1773 // code is not receiving comments from our group because
1774 // we don't feel right modifying the code to that degree
1775 // at this point in time, the precise values all begin
1776 // with the keyword precise
1777 tmpMS = Util.EnvironmentTickCount();
1778 simFrameStopwatch.Start();
1779 UpdateTerrain(); 1743 UpdateTerrain();
1780
1781 // Get the simulation frame time that the avatar force
1782 // input took
1783 simFrameStopwatch.Stop();
1784 preciseSimFrameTime =
1785 simFrameStopwatch.Elapsed.TotalMilliseconds;
1786 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS);
1787 } 1744 }
1788 1745
1789 // At several points inside the code there was a need to 1746 tmpMS2 = Util.GetTimeStampMS();
1790 // create a more precise measurement of time elapsed. This 1747 terrainMS = (float)(tmpMS2 - tmpMS);
1791 // led to the addition of variables that have a similar 1748 tmpMS = tmpMS2;
1792 // function and thus remain tightly connected to their
1793 // original counterparts. However, the original code is
1794 // not receiving comments from our group because we don't
1795 // feel right modifying the code to that degree at this
1796 // point in time, the precise values all begin with the
1797 // keyword precise
1798 1749
1799 tmpMS = Util.EnvironmentTickCount();
1800
1801 // Begin the stopwatch to track the time to prepare physics
1802 physicsFrameStopwatch.Start();
1803 if (PhysicsEnabled && Frame % m_update_physics == 0) 1750 if (PhysicsEnabled && Frame % m_update_physics == 0)
1804 m_sceneGraph.UpdatePreparePhysics(); 1751 m_sceneGraph.UpdatePreparePhysics();
1805 1752
1806 // Get the time it took to prepare the physics, this 1753 tmpMS2 = Util.GetTimeStampMS();
1807 // would report the most precise time that physics was 1754 physicsMS2 = (float)(tmpMS2 - tmpMS);
1808 // running on the machine and should the physics not be 1755 tmpMS = tmpMS2;
1809 // enabled will report the time it took to check if physics
1810 // was enabled
1811 physicsFrameStopwatch.Stop();
1812 precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds;
1813 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS);
1814 1756
1815 // Apply any pending avatar force input to the avatar's velocity 1757 // Apply any pending avatar force input to the avatar's velocity
1816 tmpMS = Util.EnvironmentTickCount();
1817 simFrameStopwatch.Restart();
1818 if (Frame % m_update_entitymovement == 0) 1758 if (Frame % m_update_entitymovement == 0)
1819 m_sceneGraph.UpdateScenePresenceMovement(); 1759 m_sceneGraph.UpdateScenePresenceMovement();
1820 1760
1821 // Get the simulation frame time that the avatar force input 1761 // Get the simulation frame time that the avatar force input
1822 // took 1762 // took
1823 simFrameStopwatch.Stop(); 1763 tmpMS2 = Util.GetTimeStampMS();
1824 preciseSimFrameTime += 1764 agentMS = (float)(tmpMS2 - tmpMS);
1825 simFrameStopwatch.Elapsed.TotalMilliseconds; 1765 tmpMS = tmpMS2;
1826 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1827 1766
1828 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1767 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1829 // velocity 1768 // velocity
1830 tmpMS = Util.EnvironmentTickCount();
1831 physicsFrameStopwatch.Restart();
1832 if (Frame % m_update_physics == 0) 1769 if (Frame % m_update_physics == 0)
1833 { 1770 {
1834 if (PhysicsEnabled) 1771 if (PhysicsEnabled)
1835 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); 1772 physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime);
1836 1773
1837 if (SynchronizeScene != null) 1774 if (SynchronizeScene != null)
1838 SynchronizeScene(this); 1775 SynchronizeScene(this);
1839 } 1776 }
1840 1777
1841 // Add the main physics update time to the prepare physics time 1778 tmpMS2 = Util.GetTimeStampMS();
1842 physicsFrameStopwatch.Stop(); 1779 physicsMS = (float)(tmpMS2 - tmpMS);
1843 precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; 1780 tmpMS = tmpMS2;
1844 physicsMS = Util.EnvironmentTickCountSubtract(tmpMS);
1845
1846 // Start the stopwatch for the remainder of the simulation
1847 simFrameStopwatch.Restart();
1848 tmpMS = Util.EnvironmentTickCount();
1849 1781
1850 // Check if any objects have reached their targets 1782 // Check if any objects have reached their targets
1851 CheckAtTargets(); 1783 CheckAtTargets();
@@ -1860,20 +1792,36 @@ namespace OpenSim.Region.Framework.Scenes
1860 if (Frame % m_update_presences == 0) 1792 if (Frame % m_update_presences == 0)
1861 m_sceneGraph.UpdatePresences(); 1793 m_sceneGraph.UpdatePresences();
1862 1794
1863 agentMS += Util.EnvironmentTickCountSubtract(tmpMS); 1795 tmpMS2 = Util.GetTimeStampMS();
1864 1796 agentMS += (float)(tmpMS2 - tmpMS);
1797 tmpMS = tmpMS2;
1798
1799 // Delete temp-on-rez stuff
1800 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1801 {
1802 m_cleaningTemps = true;
1803 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
1804 tmpMS2 = Util.GetTimeStampMS();
1805 tempOnRezMS = (float)(tmpMS2 - tmpMS); // bad.. counts the FireAndForget, not CleanTempObjects
1806 tmpMS = tmpMS2;
1807 }
1808
1865 if (Frame % m_update_events == 0) 1809 if (Frame % m_update_events == 0)
1866 { 1810 {
1867 tmpMS = Util.EnvironmentTickCount();
1868 UpdateEvents(); 1811 UpdateEvents();
1869 eventMS = Util.EnvironmentTickCountSubtract(tmpMS); 1812
1813 tmpMS2 = Util.GetTimeStampMS();
1814 eventMS = (float)(tmpMS2 - tmpMS);
1815 tmpMS = tmpMS2;
1870 } 1816 }
1871 1817
1872 if (PeriodicBackup && Frame % m_update_backup == 0) 1818 if (PeriodicBackup && Frame % m_update_backup == 0)
1873 { 1819 {
1874 tmpMS = Util.EnvironmentTickCount();
1875 UpdateStorageBackup(); 1820 UpdateStorageBackup();
1876 backupMS = Util.EnvironmentTickCountSubtract(tmpMS); 1821
1822 tmpMS2 = Util.GetTimeStampMS();
1823 backupMS = (float)(tmpMS2 - tmpMS);
1824 tmpMS = tmpMS2;
1877 } 1825 }
1878 1826
1879 //if (Frame % m_update_land == 0) 1827 //if (Frame % m_update_land == 0)
@@ -1930,79 +1878,64 @@ namespace OpenSim.Region.Framework.Scenes
1930 } 1878 }
1931 1879
1932 EventManager.TriggerRegionHeartbeatEnd(this); 1880 EventManager.TriggerRegionHeartbeatEnd(this);
1933 otherMS = eventMS + backupMS + terrainMS + landMS; 1881 m_firstHeartbeat = false;
1882 Watchdog.UpdateThread();
1934 1883
1935 // Get the elapsed time for the simulation frame 1884 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1936 simFrameStopwatch.Stop();
1937 preciseSimFrameTime +=
1938 simFrameStopwatch.Elapsed.TotalMilliseconds;
1939 1885
1940 if (!UpdateOnTimer) 1886 tmpMS = Util.GetTimeStampMS();
1941 {
1942 Watchdog.UpdateThread();
1943 1887
1944 spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); 1888 previousFrameTick = m_lastFrameTick;
1889 m_lastFrameTick = (int)(tmpMS + 0.5);
1945 1890
1946 if (spareMS > 0) 1891 // estimate sleep time
1947 m_updateWaitEvent.WaitOne(spareMS); 1892 tmpMS2 = tmpMS - framestart;
1948 else 1893 tmpMS2 = (double)frameTimeMS - tmpMS2 - sleepError;
1949 spareMS = 0;
1950 }
1951 else
1952 {
1953 spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS);
1954 }
1955 1894
1956 // Get the total frame time 1895 // reuse frameMS as temporary
1957 totalFrameStopwatch.Stop(); 1896 frameMS = (float)tmpMS2;
1958 preciseTotalFrameTime = 1897
1959 totalFrameStopwatch.Elapsed.TotalMilliseconds; 1898 // sleep if we can
1899 if (tmpMS2 > 0)
1900 {
1901 Thread.Sleep((int)(tmpMS2 + 0.5));
1960 1902
1961 // Restart the stopwatch for the total time of the next frame 1903 tmpMS2 = Util.GetTimeStampMS();
1962 totalFrameStopwatch.Restart(); 1904 sleepMS = (float)(tmpMS2 - tmpMS);
1905 sleepError = sleepMS - frameMS;
1906 Util.Clamp(sleepError, 0.0f, 20f);
1907 frameMS = (float)(tmpMS2 - framestart);
1908 }
1909 else
1910 {
1911 tmpMS2 = Util.GetTimeStampMS();
1912 frameMS = (float)(tmpMS2 - framestart);
1913 sleepMS = 0.0f;
1914 sleepError = 0.0f;
1915 }
1963 1916
1964 previousFrameTick = m_lastFrameTick; 1917 // script time is not scene frame time, but is displayed per frame
1965 frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); 1918 float scriptTimeMS = GetAndResetScriptExecutionTime();
1966 m_lastFrameTick = Util.EnvironmentTickCount(); 1919 StatsReporter.AddFrameStats(TimeDilation, physicsFPS, agentMS,
1920 physicsMS + physicsMS2, otherMS , sleepMS, frameMS, scriptTimeMS);
1921
1922
1967 1923
1968 // if (Frame%m_update_avatars == 0) 1924 // if (Frame%m_update_avatars == 0)
1969 // UpdateInWorldTime(); 1925 // UpdateInWorldTime();
1970 StatsReporter.AddPhysicsFPS(physicsFPS);
1971 StatsReporter.AddTimeDilation(TimeDilation);
1972 StatsReporter.AddFPS(1);
1973
1974 StatsReporter.addFrameMS(frameMS);
1975 StatsReporter.addAgentMS(agentMS);
1976 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1977 StatsReporter.addOtherMS(otherMS);
1978 StatsReporter.AddSpareMS(spareMS);
1979 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1980 StatsReporter.AddScriptMS((int) GetAndResetScriptExecutionTime());
1981
1982 // Send the correct time values to the stats reporter for the
1983 // frame times
1984 StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime,
1985 preciseSimFrameTime, precisePhysicsFrameTime, 0.0);
1986
1987 // Send the correct number of frames that the physics library
1988 // has processed to the stats reporter
1989 StatsReporter.addPhysicsFrame(1);
1990 1926
1991 // Optionally warn if a frame takes double the amount of time that it should. 1927 // Optionally warn if a frame takes double the amount of time that it should.
1992 if (DebugUpdates 1928 if (DebugUpdates
1993 && Util.EnvironmentTickCountSubtract( 1929 && Util.EnvironmentTickCountSubtract(
1994 m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) 1930 m_lastFrameTick, previousFrameTick) > (int)(FrameTime * 1000 * 2))
1931
1995 m_log.WarnFormat( 1932 m_log.WarnFormat(
1996 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", 1933 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
1997 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), 1934 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick),
1998 MinFrameTicks, 1935 FrameTime * 1000,
1936
1999 RegionInfo.RegionName); 1937 RegionInfo.RegionName);
2000 } 1938 }
2001
2002 // Finished updating scene frame, so stop the total frame's Stopwatch
2003 totalFrameStopwatch.Stop();
2004
2005 return spareMS >= 0;
2006 } 1939 }
2007 1940
2008 /// <summary> 1941 /// <summary>
@@ -2011,24 +1944,28 @@ namespace OpenSim.Region.Framework.Scenes
2011 /// <param name="ticks">Elapsed Stopwatch ticks</param> 1944 /// <param name="ticks">Elapsed Stopwatch ticks</param>
2012 public void AddScriptExecutionTime(long ticks) 1945 public void AddScriptExecutionTime(long ticks)
2013 { 1946 {
1947 StatsReporter.addScriptEvents(1);
2014 Interlocked.Add(ref m_scriptExecutionTime, ticks); 1948 Interlocked.Add(ref m_scriptExecutionTime, ticks);
2015 } 1949 }
2016 1950
2017 /// <summary> 1951 /// <summary>
2018 /// Returns the total execution time of all the scripts in the region since the last frame 1952 /// Returns the total execution time of all the scripts in the region since the last call
2019 /// (in milliseconds), and clears the value in preparation for the next frame. 1953 /// (in milliseconds), and clears the value in preparation for the next call.
2020 /// </summary> 1954 /// </summary>
2021 /// <returns>Time in milliseconds</returns> 1955 /// <returns>Time in milliseconds</returns>
2022 private long GetAndResetScriptExecutionTime() 1956
1957 // Warning: this is now called from StatsReporter, and can't be shared
1958
1959 public long GetAndResetScriptExecutionTime()
2023 { 1960 {
2024 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0); 1961 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0);
2025 return (ticks * 1000) / Stopwatch.Frequency; 1962 return (ticks * 1000L) / Stopwatch.Frequency;
2026 } 1963 }
2027 1964
2028 public void AddGroupTarget(SceneObjectGroup grp) 1965 public void AddGroupTarget(SceneObjectGroup grp)
2029 { 1966 {
2030 lock (m_groupsWithTargets) 1967 lock (m_groupsWithTargets)
2031 m_groupsWithTargets[grp.UUID] = grp; 1968 m_groupsWithTargets[grp.UUID] = 0;
2032 } 1969 }
2033 1970
2034 public void RemoveGroupTarget(SceneObjectGroup grp) 1971 public void RemoveGroupTarget(SceneObjectGroup grp)
@@ -2039,18 +1976,24 @@ namespace OpenSim.Region.Framework.Scenes
2039 1976
2040 private void CheckAtTargets() 1977 private void CheckAtTargets()
2041 { 1978 {
2042 List<SceneObjectGroup> objs = null; 1979 List<UUID> objs = null;
2043 1980
2044 lock (m_groupsWithTargets) 1981 lock (m_groupsWithTargets)
2045 { 1982 {
2046 if (m_groupsWithTargets.Count != 0) 1983 if (m_groupsWithTargets.Count != 0)
2047 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); 1984 objs = new List<UUID>(m_groupsWithTargets.Keys);
2048 } 1985 }
2049 1986
2050 if (objs != null) 1987 if (objs != null)
2051 { 1988 {
2052 foreach (SceneObjectGroup entry in objs) 1989 foreach (UUID entry in objs)
2053 entry.checkAtTargets(); 1990 {
1991 SceneObjectGroup grp = GetSceneObjectGroup(entry);
1992 if (grp == null)
1993 m_groupsWithTargets.Remove(entry);
1994 else
1995 grp.checkAtTargets();
1996 }
2054 } 1997 }
2055 } 1998 }
2056 1999
@@ -2074,6 +2017,11 @@ namespace OpenSim.Region.Framework.Scenes
2074 EventManager.TriggerTerrainTick(); 2017 EventManager.TriggerTerrainTick();
2075 } 2018 }
2076 2019
2020 private void CheckTerrainUpdates()
2021 {
2022 EventManager.TriggerTerrainCheckUpdates();
2023 }
2024
2077 /// <summary> 2025 /// <summary>
2078 /// Back up queued up changes 2026 /// Back up queued up changes
2079 /// </summary> 2027 /// </summary>
@@ -2125,7 +2073,7 @@ namespace OpenSim.Region.Framework.Scenes
2125 msg.fromAgentName = "Server"; 2073 msg.fromAgentName = "Server";
2126 msg.dialog = (byte)19; // Object msg 2074 msg.dialog = (byte)19; // Object msg
2127 msg.fromGroup = false; 2075 msg.fromGroup = false;
2128 msg.offline = (byte)0; 2076 msg.offline = (byte)1;
2129 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 2077 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
2130 msg.Position = Vector3.Zero; 2078 msg.Position = Vector3.Zero;
2131 msg.RegionID = RegionInfo.RegionID.Guid; 2079 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -2277,7 +2225,7 @@ namespace OpenSim.Region.Framework.Scenes
2277 //// stored in the GridService, because that's what the world map module uses 2225 //// stored in the GridService, because that's what the world map module uses
2278 //// to send the map image UUIDs (of other regions) to the viewer... 2226 //// to send the map image UUIDs (of other regions) to the viewer...
2279 if (m_generateMaptiles) 2227 if (m_generateMaptiles)
2280 RegenerateMaptile(); 2228 RegenerateMaptile();
2281 2229
2282 GridRegion region = new GridRegion(RegionInfo); 2230 GridRegion region = new GridRegion(RegionInfo);
2283 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2231 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
@@ -2361,7 +2309,7 @@ namespace OpenSim.Region.Framework.Scenes
2361 return PhysicsScene.SupportsRaycastWorldFiltered(); 2309 return PhysicsScene.SupportsRaycastWorldFiltered();
2362 } 2310 }
2363 2311
2364 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) 2312 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
2365 { 2313 {
2366 if (PhysicsScene == null) 2314 if (PhysicsScene == null)
2367 return null; 2315 return null;
@@ -2383,93 +2331,166 @@ namespace OpenSim.Region.Framework.Scenes
2383 /// <returns></returns> 2331 /// <returns></returns>
2384 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 2332 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
2385 { 2333 {
2386 Vector3 pos = Vector3.Zero;
2387 if (RayEndIsIntersection == (byte)1)
2388 {
2389 pos = RayEnd;
2390 return pos;
2391 }
2392 2334
2393 if (RayTargetID != UUID.Zero) 2335 Vector3 dir = RayEnd - RayStart;
2336
2337 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
2338 Vector3 wpos = Vector3.Zero;
2339 // Check for water surface intersection from above
2340 if ((RayStart.Z > wheight) && (RayEnd.Z < wheight))
2394 { 2341 {
2395 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 2342 float ratio = (wheight - RayStart.Z) / dir.Z;
2343 wpos.X = RayStart.X + (ratio * dir.X);
2344 wpos.Y = RayStart.Y + (ratio * dir.Y);
2345 wpos.Z = wheight;
2346 }
2396 2347
2397 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 2348 Vector3 pos = Vector3.Zero;
2398 Vector3 AXOrigin = RayStart;
2399 Vector3 AXdirection = direction;
2400 2349
2401 if (target != null) 2350 if (RayEndIsIntersection != (byte)1)
2351 {
2352 float dist = dir.Length();
2353 if (dist != 0)
2402 { 2354 {
2403 pos = target.AbsolutePosition; 2355 Vector3 direction = dir * (1 / dist);
2404 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
2405 2356
2406 // TODO: Raytrace better here 2357 dist += 1.0f;
2407 2358
2408 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 2359 if (SupportsRayCastFiltered())
2409 Ray NewRay = new Ray(AXOrigin, AXdirection); 2360 {
2361 RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
2362 rayfilter |= RayFilterFlags.land;
2363 rayfilter |= RayFilterFlags.physical;
2364 rayfilter |= RayFilterFlags.nonphysical;
2365 rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors
2366
2367 // get some more contacts ???
2368 int physcount = 4;
2369
2370 List<ContactResult> physresults =
2371 (List<ContactResult>)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
2372 if (physresults != null && physresults.Count > 0)
2373 {
2374 // look for terrain ?
2375 if(RayTargetID == UUID.Zero)
2376 {
2377 foreach (ContactResult r in physresults)
2378 {
2379 if (r.ConsumerID == 0)
2380 {
2381 pos = r.Normal * scale;
2382 pos *= 0.5f;
2383 pos = r.Pos + pos;
2384
2385 if (wpos.Z > pos.Z) pos = wpos;
2386 return pos;
2387 }
2388 }
2389 }
2390 else
2391 {
2392 foreach (ContactResult r in physresults)
2393 {
2394 SceneObjectPart part = GetSceneObjectPart(r.ConsumerID);
2395 if (part == null)
2396 continue;
2397 if (part.UUID == RayTargetID)
2398 {
2399 pos = r.Normal * scale;
2400 pos *= 0.5f;
2401 pos = r.Pos + pos;
2402
2403 if (wpos.Z > pos.Z) pos = wpos;
2404 return pos;
2405 }
2406 }
2407 }
2408 // else the first we got
2409 pos = physresults[0].Normal * scale;
2410 pos *= 0.5f;
2411 pos = physresults[0].Pos + pos;
2412
2413 if (wpos.Z > pos.Z)
2414 pos = wpos;
2415 return pos;
2416 }
2410 2417
2411 // Ray Trace against target here 2418 }
2412 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 2419 if (RayTargetID != UUID.Zero)
2420 {
2421 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
2413 2422
2414 // Un-comment out the following line to Get Raytrace results printed to the console. 2423 Ray NewRay = new Ray(RayStart, direction);
2415 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2416 float ScaleOffset = 0.5f;
2417 2424
2418 // If we hit something 2425 if (target != null)
2419 if (ei.HitTF) 2426 {
2420 { 2427 pos = target.AbsolutePosition;
2421 Vector3 scaleComponent = ei.AAfaceNormal;
2422 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2423 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2424 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2425 ScaleOffset = Math.Abs(ScaleOffset);
2426 Vector3 intersectionpoint = ei.ipoint;
2427 Vector3 normal = ei.normal;
2428 // Set the position to the intersection point
2429 Vector3 offset = (normal * (ScaleOffset / 2f));
2430 pos = (intersectionpoint + offset);
2431
2432 //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
2433 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2434 // Un-offset the prim (it gets offset later by the consumer method)
2435 //pos.Z -= 0.25F;
2436 2428
2437 } 2429 // Ray Trace against target here
2430 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
2438 2431
2439 return pos; 2432 // Un-comment out the following line to Get Raytrace results printed to the console.
2440 } 2433 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2441 else 2434 float ScaleOffset = 0.5f;
2442 {
2443 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2444 2435
2445 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2436 // If we hit something
2437 if (ei.HitTF)
2438 {
2439 Vector3 scaleComponent = ei.AAfaceNormal;
2440 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2441 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2442 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2443 ScaleOffset = Math.Abs(ScaleOffset);
2444 Vector3 intersectionpoint = ei.ipoint;
2445 Vector3 normal = ei.normal;
2446 // Set the position to the intersection point
2447 Vector3 offset = (normal * (ScaleOffset / 2f));
2448 pos = (intersectionpoint + offset);
2449
2450 //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
2451 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2452 // Un-offset the prim (it gets offset later by the consumer method)
2453 //pos.Z -= 0.25F;
2454
2455 if (wpos.Z > pos.Z) pos = wpos;
2456 return pos;
2457 }
2458 }
2459 else
2460 {
2461 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2462 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(NewRay, true, false);
2446 2463
2447 // Un-comment the following line to print the raytrace results to the console. 2464 // Un-comment the following line to print the raytrace results to the console.
2448 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 2465 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2449 2466
2450 if (ei.HitTF) 2467 if (ei.HitTF)
2451 { 2468 {
2452 pos = ei.ipoint; 2469 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
2453 } 2470 }
2454 else 2471 else
2455 { 2472 {
2456 // fall back to our stupid functionality 2473 // fall back to our stupid functionality
2457 pos = RayEnd; 2474 pos = RayEnd;
2458 } 2475 }
2459 2476
2460 return pos; 2477 if (wpos.Z > pos.Z) pos = wpos;
2478 return pos;
2479 }
2480 }
2461 } 2481 }
2462 } 2482 }
2463 else
2464 {
2465 // fall back to our stupid functionality
2466 pos = RayEnd;
2467 2483
2468 //increase height so its above the ground. 2484 // fall back to our stupid functionality
2469 //should be getting the normal of the ground at the rez point and using that? 2485 pos = RayEnd;
2470 pos.Z += scale.Z / 2f; 2486
2471 return pos; 2487 //increase height so its above the ground.
2472 } 2488 //should be getting the normal of the ground at the rez point and using that?
2489 pos.Z += scale.Z / 2f;
2490 // return pos;
2491 // check against posible water intercept
2492 if (wpos.Z > pos.Z) pos = wpos;
2493 return pos;
2473 } 2494 }
2474 2495
2475 2496
@@ -2560,12 +2581,12 @@ namespace OpenSim.Region.Framework.Scenes
2560 { 2581 {
2561 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) 2582 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2562 { 2583 {
2584 sceneObject.IsDeleted = false;
2563 EventManager.TriggerObjectAddedToScene(sceneObject); 2585 EventManager.TriggerObjectAddedToScene(sceneObject);
2564 return true; 2586 return true;
2565 } 2587 }
2566 2588
2567 return false; 2589 return false;
2568
2569 } 2590 }
2570 2591
2571 /// <summary> 2592 /// <summary>
@@ -2657,6 +2678,15 @@ namespace OpenSim.Region.Framework.Scenes
2657 /// </summary> 2678 /// </summary>
2658 public void DeleteAllSceneObjects() 2679 public void DeleteAllSceneObjects()
2659 { 2680 {
2681 DeleteAllSceneObjects(false);
2682 }
2683
2684 /// <summary>
2685 /// Delete every object from the scene. This does not include attachments worn by avatars.
2686 /// </summary>
2687 public void DeleteAllSceneObjects(bool exceptNoCopy)
2688 {
2689 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2660 lock (Entities) 2690 lock (Entities)
2661 { 2691 {
2662 EntityBase[] entities = Entities.GetEntities(); 2692 EntityBase[] entities = Entities.GetEntities();
@@ -2665,11 +2695,24 @@ namespace OpenSim.Region.Framework.Scenes
2665 if (e is SceneObjectGroup) 2695 if (e is SceneObjectGroup)
2666 { 2696 {
2667 SceneObjectGroup sog = (SceneObjectGroup)e; 2697 SceneObjectGroup sog = (SceneObjectGroup)e;
2668 if (!sog.IsAttachment) 2698 if (sog != null && !sog.IsAttachment)
2669 DeleteSceneObject((SceneObjectGroup)e, false); 2699 {
2700 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2701 {
2702 DeleteSceneObject((SceneObjectGroup)e, false);
2703 }
2704 else
2705 {
2706 toReturn.Add((SceneObjectGroup)e);
2707 }
2708 }
2670 } 2709 }
2671 } 2710 }
2672 } 2711 }
2712 if (toReturn.Count > 0)
2713 {
2714 returnObjects(toReturn.ToArray(), UUID.Zero);
2715 }
2673 } 2716 }
2674 2717
2675 /// <summary> 2718 /// <summary>
@@ -2700,6 +2743,13 @@ namespace OpenSim.Region.Framework.Scenes
2700 else 2743 else
2701 group.StopScriptInstances(); 2744 group.StopScriptInstances();
2702 2745
2746 List<ScenePresence> avatars = group.GetSittingAvatars();
2747 foreach (ScenePresence av in avatars)
2748 {
2749 if(av.ParentUUID == UUID.Zero)
2750 av.StandUp();
2751 }
2752
2703 SceneObjectPart[] partList = group.Parts; 2753 SceneObjectPart[] partList = group.Parts;
2704 2754
2705 foreach (SceneObjectPart part in partList) 2755 foreach (SceneObjectPart part in partList)
@@ -2727,6 +2777,8 @@ namespace OpenSim.Region.Framework.Scenes
2727 } 2777 }
2728 2778
2729 group.DeleteGroupFromScene(silent); 2779 group.DeleteGroupFromScene(silent);
2780 if (!silent)
2781 SendKillObject(new List<uint>() { group.LocalId });
2730 2782
2731 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2783 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2732 } 2784 }
@@ -2763,6 +2815,13 @@ namespace OpenSim.Region.Framework.Scenes
2763 return false; 2815 return false;
2764 } 2816 }
2765 2817
2818
2819 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
2820 {
2821 m_sceneGraph.updateScenePartGroup(part, grp);
2822 }
2823
2824/* not in use, outdate by async method
2766 /// <summary> 2825 /// <summary>
2767 /// Move the given scene object into a new region depending on which region its absolute position has moved 2826 /// Move the given scene object into a new region depending on which region its absolute position has moved
2768 /// into. 2827 /// into.
@@ -2811,6 +2870,7 @@ namespace OpenSim.Region.Framework.Scenes
2811 if (EntityTransferModule != null) 2870 if (EntityTransferModule != null)
2812 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2871 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2813 } 2872 }
2873*/
2814 2874
2815 // Simple test to see if a position is in the current region. 2875 // Simple test to see if a position is in the current region.
2816 // This test is mostly used to see if a region crossing is necessary. 2876 // This test is mostly used to see if a region crossing is necessary.
@@ -2828,7 +2888,7 @@ namespace OpenSim.Region.Framework.Scenes
2828 if (regionCombinerModule == null) 2888 if (regionCombinerModule == null)
2829 { 2889 {
2830 // Regular region. Just check for region size 2890 // Regular region. Just check for region size
2831 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY) 2891 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY )
2832 ret = true; 2892 ret = true;
2833 } 2893 }
2834 else 2894 else
@@ -2836,9 +2896,7 @@ namespace OpenSim.Region.Framework.Scenes
2836 // We're in a mega-region so see if we are still in that larger region 2896 // We're in a mega-region so see if we are still in that larger region
2837 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy); 2897 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
2838 } 2898 }
2839
2840 return ret; 2899 return ret;
2841
2842 } 2900 }
2843 2901
2844 /// <summary> 2902 /// <summary>
@@ -2862,8 +2920,52 @@ namespace OpenSim.Region.Framework.Scenes
2862 return false; 2920 return false;
2863 } 2921 }
2864 2922
2865 if (!EntityTransferModule.HandleIncomingSceneObject(newObject, newPosition)) 2923 // If the user is banned, we won't let any of their objects
2924 // enter. Period.
2925 //
2926 if (RegionInfo.EstateSettings.IsBanned(newObject.OwnerID, 36))
2927 {
2928 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", newObject.OwnerID);
2866 return false; 2929 return false;
2930 }
2931
2932 if (newPosition != Vector3.Zero)
2933 newObject.RootPart.GroupPosition = newPosition;
2934
2935 if (!AddSceneObject(newObject))
2936 {
2937 m_log.DebugFormat(
2938 "[INTERREGION]: Problem adding scene object {0} in {1} ", newObject.UUID, RegionInfo.RegionName);
2939 return false;
2940 }
2941
2942 if (!newObject.IsAttachment)
2943 {
2944 // FIXME: It would be better to never add the scene object at all rather than add it and then delete
2945 // it
2946 if (!Permissions.CanObjectEntry(newObject.UUID, true, newObject.AbsolutePosition))
2947 {
2948 // Deny non attachments based on parcel settings
2949 //
2950 m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings");
2951
2952 DeleteSceneObject(newObject, false);
2953
2954 return false;
2955 }
2956
2957 // For attachments, we need to wait until the agent is root
2958 // before we restart the scripts, or else some functions won't work.
2959 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
2960 newObject.ResumeScripts();
2961
2962 // AddSceneObject already does this and doing it again messes
2963 // up region crossings, so don't.
2964 //if (newObject.RootPart.KeyframeMotion != null)
2965 // newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2966 }
2967
2968
2867 2969
2868 // Do this as late as possible so that listeners have full access to the incoming object 2970 // Do this as late as possible so that listeners have full access to the incoming object
2869 EventManager.TriggerOnIncomingSceneObject(newObject); 2971 EventManager.TriggerOnIncomingSceneObject(newObject);
@@ -2880,6 +2982,23 @@ namespace OpenSim.Region.Framework.Scenes
2880 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2982 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2881 public bool AddSceneObject(SceneObjectGroup sceneObject) 2983 public bool AddSceneObject(SceneObjectGroup sceneObject)
2882 { 2984 {
2985 if (sceneObject.OwnerID == UUID.Zero)
2986 {
2987 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2988 return false;
2989 }
2990
2991 // If the user is banned, we won't let any of their objects
2992 // enter. Period.
2993 //
2994 int flags = GetUserFlags(sceneObject.OwnerID);
2995 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2996 {
2997 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2998
2999 return false;
3000 }
3001
2883 // Force allocation of new LocalId 3002 // Force allocation of new LocalId
2884 // 3003 //
2885 SceneObjectPart[] parts = sceneObject.Parts; 3004 SceneObjectPart[] parts = sceneObject.Parts;
@@ -2916,22 +3035,62 @@ namespace OpenSim.Region.Framework.Scenes
2916 // information that this is due to a teleport/border cross rather than an ordinary attachment. 3035 // information that this is due to a teleport/border cross rather than an ordinary attachment.
2917 // We currently do this in Scene.MakeRootAgent() instead. 3036 // We currently do this in Scene.MakeRootAgent() instead.
2918 if (AttachmentsModule != null) 3037 if (AttachmentsModule != null)
2919 AttachmentsModule.AttachObject(sp, grp, 0, false, false, true); 3038 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
2920 } 3039 }
2921 else 3040 else
2922 { 3041 {
3042 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2923 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 3043 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2924 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 3044 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2925 } 3045 }
3046 if (sceneObject.OwnerID == UUID.Zero)
3047 {
3048 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
3049 return false;
3050 }
2926 } 3051 }
2927 else 3052 else
2928 { 3053 {
3054 if (sceneObject.OwnerID == UUID.Zero)
3055 {
3056 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
3057 return false;
3058 }
2929 AddRestoredSceneObject(sceneObject, true, false); 3059 AddRestoredSceneObject(sceneObject, true, false);
2930 } 3060 }
2931 3061
2932 return true; 3062 return true;
2933 } 3063 }
2934 3064
3065 private int GetStateSource(SceneObjectGroup sog)
3066 {
3067 ScenePresence sp = GetScenePresence(sog.OwnerID);
3068
3069 if (sp != null)
3070 return sp.GetStateSource();
3071
3072 return 2; // StateSource.PrimCrossing
3073 }
3074
3075 public int GetUserFlags(UUID user)
3076 {
3077 //Unfortunately the SP approach means that the value is cached until region is restarted
3078 /*
3079 ScenePresence sp;
3080 if (TryGetScenePresence(user, out sp))
3081 {
3082 return sp.UserFlags;
3083 }
3084 else
3085 {
3086 */
3087 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
3088 if (uac == null)
3089 return 0;
3090 return uac.UserFlags;
3091 //}
3092 }
3093
2935 #endregion 3094 #endregion
2936 3095
2937 #region Add/Remove Avatar Methods 3096 #region Add/Remove Avatar Methods
@@ -2967,8 +3126,9 @@ namespace OpenSim.Region.Framework.Scenes
2967 vialogin 3126 vialogin
2968 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 3127 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2969 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 3128 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2970 3129
2971 // CheckHeartbeat(); 3130 CheckHeartbeat();
3131
2972 3132
2973 sp = GetScenePresence(client.AgentId); 3133 sp = GetScenePresence(client.AgentId);
2974 3134
@@ -2979,27 +3139,27 @@ namespace OpenSim.Region.Framework.Scenes
2979 if (sp == null) 3139 if (sp == null)
2980 { 3140 {
2981 m_log.DebugFormat( 3141 m_log.DebugFormat(
2982 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 3142 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}, tpflags: {4}",
2983 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 3143 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos,
2984 3144 ((TPFlags)aCircuit.teleportFlags).ToString());
2985 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); 3145
2986
2987 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2988 // client is for a root or child agent.
2989 // We must also set this before adding the client to the client manager so that an exception later on
2990 // does not leave a client manager entry without the scene agent set, which will cause other code
2991 // to fail since any entry in the client manager should have a ScenePresence
2992 //
2993 // XXX: This may be better set for a new client before that client is added to the client manager.
2994 // But need to know what happens in the case where a ScenePresence is already present (and if this
2995 // actually occurs).
2996 client.SceneAgent = sp;
2997
2998 m_clientManager.Add(client); 3146 m_clientManager.Add(client);
2999 SubscribeToClientEvents(client); 3147 SubscribeToClientEvents(client);
3000 m_eventManager.TriggerOnNewPresence(sp); 3148
3149 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
3001 3150
3002 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 3151 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
3152
3153/* done in completMovement
3154 InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
3155 if (cof == null)
3156 sp.COF = UUID.Zero;
3157 else
3158 sp.COF = cof.ID;
3159
3160 m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF);
3161 */
3162 m_eventManager.TriggerOnNewPresence(sp);
3003 } 3163 }
3004 else 3164 else
3005 { 3165 {
@@ -3008,7 +3168,7 @@ namespace OpenSim.Region.Framework.Scenes
3008 // XXX: This may be better set for a new client before that client is added to the client manager. 3168 // XXX: This may be better set for a new client before that client is added to the client manager.
3009 // But need to know what happens in the case where a ScenePresence is already present (and if this 3169 // But need to know what happens in the case where a ScenePresence is already present (and if this
3010 // actually occurs). 3170 // actually occurs).
3011 client.SceneAgent = sp; 3171
3012 3172
3013 m_log.WarnFormat( 3173 m_log.WarnFormat(
3014 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3174 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
@@ -3016,6 +3176,7 @@ namespace OpenSim.Region.Framework.Scenes
3016 3176
3017 reallyNew = false; 3177 reallyNew = false;
3018 } 3178 }
3179 client.SceneAgent = sp;
3019 3180
3020 // This is currently also being done earlier in NewUserConnection for real users to see if this 3181 // This is currently also being done earlier in NewUserConnection for real users to see if this
3021 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other 3182 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
@@ -3134,19 +3295,15 @@ namespace OpenSim.Region.Framework.Scenes
3134 // and the scene presence and the client, if they exist 3295 // and the scene presence and the client, if they exist
3135 try 3296 try
3136 { 3297 {
3137 // We need to wait for the client to make UDP contact first.
3138 // It's the UDP contact that creates the scene presence
3139 ScenePresence sp = WaitGetScenePresence(agentID); 3298 ScenePresence sp = WaitGetScenePresence(agentID);
3299
3140 if (sp != null) 3300 if (sp != null)
3141 { 3301 {
3142 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3302 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3143 3303
3144 CloseAgent(sp.UUID, false); 3304 CloseAgent(sp.UUID, false);
3145 } 3305 }
3146 else 3306
3147 {
3148 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
3149 }
3150 // BANG! SLASH! 3307 // BANG! SLASH!
3151 m_authenticateHandler.RemoveCircuit(agentID); 3308 m_authenticateHandler.RemoveCircuit(agentID);
3152 3309
@@ -3183,7 +3340,7 @@ namespace OpenSim.Region.Framework.Scenes
3183 3340
3184 public virtual void SubscribeToClientTerrainEvents(IClientAPI client) 3341 public virtual void SubscribeToClientTerrainEvents(IClientAPI client)
3185 { 3342 {
3186 client.OnRegionHandShakeReply += SendLayerData; 3343// client.OnRegionHandShakeReply += SendLayerData;
3187 } 3344 }
3188 3345
3189 public virtual void SubscribeToClientPrimEvents(IClientAPI client) 3346 public virtual void SubscribeToClientPrimEvents(IClientAPI client)
@@ -3191,6 +3348,8 @@ namespace OpenSim.Region.Framework.Scenes
3191 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 3348 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
3192 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 3349 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
3193 3350
3351 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
3352
3194 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 3353 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
3195 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 3354 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
3196 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 3355 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -3247,6 +3406,7 @@ namespace OpenSim.Region.Framework.Scenes
3247 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3406 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
3248 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3407 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
3249 client.OnCopyInventoryItem += CopyInventoryItem; 3408 client.OnCopyInventoryItem += CopyInventoryItem;
3409 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
3250 client.OnMoveInventoryItem += MoveInventoryItem; 3410 client.OnMoveInventoryItem += MoveInventoryItem;
3251 client.OnRemoveInventoryItem += RemoveInventoryItem; 3411 client.OnRemoveInventoryItem += RemoveInventoryItem;
3252 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3412 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -3308,7 +3468,7 @@ namespace OpenSim.Region.Framework.Scenes
3308 3468
3309 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) 3469 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client)
3310 { 3470 {
3311 client.OnRegionHandShakeReply -= SendLayerData; 3471// client.OnRegionHandShakeReply -= SendLayerData;
3312 } 3472 }
3313 3473
3314 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) 3474 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client)
@@ -3316,6 +3476,8 @@ namespace OpenSim.Region.Framework.Scenes
3316 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3476 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
3317 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3477 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
3318 3478
3479 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3480
3319 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3481 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3320 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3482 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3321 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3483 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3473,16 +3635,14 @@ namespace OpenSim.Region.Framework.Scenes
3473 if (target != null && target2 != null) 3635 if (target != null && target2 != null)
3474 { 3636 {
3475 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 3637 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
3476 Vector3 AXOrigin = RayStart; 3638
3477 Vector3 AXdirection = direction;
3478
3479 pos = target2.AbsolutePosition; 3639 pos = target2.AbsolutePosition;
3480 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); 3640 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
3481 3641
3482 // TODO: Raytrace better here 3642 // TODO: Raytrace better here
3483 3643
3484 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 3644 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
3485 Ray NewRay = new Ray(AXOrigin, AXdirection); 3645 Ray NewRay = new Ray(RayStart,direction);
3486 3646
3487 // Ray Trace against target here 3647 // Ray Trace against target here
3488 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); 3648 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters);
@@ -3564,6 +3724,10 @@ namespace OpenSim.Region.Framework.Scenes
3564 /// <param name='closeChildAgents'> 3724 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client. 3725 /// Close the neighbour child agents associated with this client.
3566 /// </param> 3726 /// </param>
3727 ///
3728
3729 private object m_removeClientPrivLock = new Object();
3730
3567 public void RemoveClient(UUID agentID, bool closeChildAgents) 3731 public void RemoveClient(UUID agentID, bool closeChildAgents)
3568 { 3732 {
3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3733 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
@@ -3580,8 +3744,8 @@ namespace OpenSim.Region.Framework.Scenes
3580 } 3744 }
3581 3745
3582 // TODO: Can we now remove this lock? 3746 // TODO: Can we now remove this lock?
3583 lock (acd) 3747 lock (m_removeClientPrivLock)
3584 { 3748 {
3585 bool isChildAgent = false; 3749 bool isChildAgent = false;
3586 3750
3587 ScenePresence avatar = GetScenePresence(agentID); 3751 ScenePresence avatar = GetScenePresence(agentID);
@@ -3625,8 +3789,8 @@ namespace OpenSim.Region.Framework.Scenes
3625 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3789 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3626 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3790 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3627 if (closeChildAgents && CapsModule != null) 3791 if (closeChildAgents && CapsModule != null)
3628 CapsModule.RemoveCaps(agentID); 3792 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3629 3793
3630 if (closeChildAgents && !isChildAgent) 3794 if (closeChildAgents && !isChildAgent)
3631 { 3795 {
3632 List<ulong> regions = avatar.KnownRegionHandles; 3796 List<ulong> regions = avatar.KnownRegionHandles;
@@ -3637,13 +3801,17 @@ namespace OpenSim.Region.Framework.Scenes
3637 } 3801 }
3638 3802
3639 m_eventManager.TriggerClientClosed(agentID, this); 3803 m_eventManager.TriggerClientClosed(agentID, this);
3804// m_log.Debug("[Scene]TriggerClientClosed done");
3640 m_eventManager.TriggerOnRemovePresence(agentID); 3805 m_eventManager.TriggerOnRemovePresence(agentID);
3641 3806// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3807
3642 if (!isChildAgent) 3808 if (!isChildAgent)
3643 { 3809 {
3644 if (AttachmentsModule != null) 3810 if (AttachmentsModule != null)
3645 { 3811 {
3812// m_log.Debug("[Scene]DeRezAttachments");
3646 AttachmentsModule.DeRezAttachments(avatar); 3813 AttachmentsModule.DeRezAttachments(avatar);
3814// m_log.Debug("[Scene]DeRezAttachments done");
3647 } 3815 }
3648 3816
3649 ForEachClient( 3817 ForEachClient(
@@ -3657,7 +3825,11 @@ namespace OpenSim.Region.Framework.Scenes
3657 3825
3658 // It's possible for child agents to have transactions if changes are being made cross-border. 3826 // It's possible for child agents to have transactions if changes are being made cross-border.
3659 if (AgentTransactionsModule != null) 3827 if (AgentTransactionsModule != null)
3828 {
3829// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3660 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3830 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3831 }
3832 m_log.Debug("[Scene] The avatar has left the building");
3661 } 3833 }
3662 catch (Exception e) 3834 catch (Exception e)
3663 { 3835 {
@@ -3776,6 +3948,9 @@ namespace OpenSim.Region.Framework.Scenes
3776 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3948 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3777 /// <returns>True if the region accepts this agent. False if it does not. False will 3949 /// <returns>True if the region accepts this agent. False if it does not. False will
3778 /// also return a reason.</returns> 3950 /// also return a reason.</returns>
3951 ///
3952 private object m_newUserConnLock = new object();
3953
3779 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) 3954 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup)
3780 { 3955 {
3781 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3956 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
@@ -3809,6 +3984,8 @@ namespace OpenSim.Region.Framework.Scenes
3809 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) 3984 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)
3810 ); 3985 );
3811 3986
3987// m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace);
3988
3812 if (!LoginsEnabled) 3989 if (!LoginsEnabled)
3813 { 3990 {
3814 reason = "Logins Disabled"; 3991 reason = "Logins Disabled";
@@ -3936,7 +4113,7 @@ namespace OpenSim.Region.Framework.Scenes
3936 } 4113 }
3937 4114
3938 // TODO: can we remove this lock? 4115 // TODO: can we remove this lock?
3939 lock (acd) 4116 lock (m_newUserConnLock)
3940 { 4117 {
3941 if (sp != null && !sp.IsChildAgent) 4118 if (sp != null && !sp.IsChildAgent)
3942 { 4119 {
@@ -3963,6 +4140,12 @@ namespace OpenSim.Region.Framework.Scenes
3963 // We need the circuit data here for some of the subsequent checks. (groups, for example) 4140 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3964 // If the checks fail, we remove the circuit. 4141 // If the checks fail, we remove the circuit.
3965 acd.teleportFlags = teleportFlags; 4142 acd.teleportFlags = teleportFlags;
4143
4144 // Remove any preexisting circuit - we don't want duplicates
4145 // This is a stab at preventing avatar "ghosting"
4146 if (vialogin)
4147 m_authenticateHandler.RemoveCircuit(acd.AgentID);
4148
3966 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); 4149 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3967 4150
3968 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); 4151 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
@@ -3970,6 +4153,9 @@ namespace OpenSim.Region.Framework.Scenes
3970 // On login test land permisions 4153 // On login test land permisions
3971 if (vialogin) 4154 if (vialogin)
3972 { 4155 {
4156 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
4157 if (cache != null)
4158 cache.Remove(acd.firstname + " " + acd.lastname);
3973 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) 4159 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3974 { 4160 {
3975 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4161 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
@@ -4024,7 +4210,7 @@ namespace OpenSim.Region.Framework.Scenes
4024 if (CapsModule != null) 4210 if (CapsModule != null)
4025 { 4211 {
4026 CapsModule.SetAgentCapsSeeds(acd); 4212 CapsModule.SetAgentCapsSeeds(acd);
4027 CapsModule.CreateCaps(acd.AgentID); 4213 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4028 } 4214 }
4029 } 4215 }
4030 else 4216 else
@@ -4037,15 +4223,15 @@ namespace OpenSim.Region.Framework.Scenes
4037 { 4223 {
4038 m_log.DebugFormat( 4224 m_log.DebugFormat(
4039 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4225 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
4040 acd.AgentID, RegionInfo.RegionName); 4226 acd.AgentID, RegionInfo.RegionName);
4041
4042 sp.AdjustKnownSeeds();
4043 4227
4044 if (CapsModule != null) 4228 if (CapsModule != null)
4045 { 4229 {
4046 CapsModule.SetAgentCapsSeeds(acd); 4230 CapsModule.SetAgentCapsSeeds(acd);
4047 CapsModule.CreateCaps(acd.AgentID); 4231 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4048 } 4232 }
4233
4234 sp.AdjustKnownSeeds();
4049 } 4235 }
4050 } 4236 }
4051 4237
@@ -4055,6 +4241,11 @@ namespace OpenSim.Region.Framework.Scenes
4055 CacheUserName(null, acd); 4241 CacheUserName(null, acd);
4056 } 4242 }
4057 4243
4244 if (CapsModule != null)
4245 {
4246 CapsModule.ActivateCaps(acd.circuitcode);
4247 }
4248
4058 if (vialogin) 4249 if (vialogin)
4059 { 4250 {
4060// CleanDroppedAttachments(); 4251// CleanDroppedAttachments();
@@ -4124,6 +4315,8 @@ namespace OpenSim.Region.Framework.Scenes
4124 } 4315 }
4125 4316
4126 // Honor parcel landing type and position. 4317 // Honor parcel landing type and position.
4318 /*
4319 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
4127 if (land != null) 4320 if (land != null)
4128 { 4321 {
4129 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4322 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -4138,6 +4331,7 @@ namespace OpenSim.Region.Framework.Scenes
4138 } 4331 }
4139 } 4332 }
4140 } 4333 }
4334 */// This is now handled properly in ScenePresence.MakeRootAgent
4141 } 4335 }
4142 4336
4143 return true; 4337 return true;
@@ -4162,12 +4356,13 @@ namespace OpenSim.Region.Framework.Scenes
4162 { 4356 {
4163 if (posX < 0) 4357 if (posX < 0)
4164 posX = 0; 4358 posX = 0;
4165 else if (posX >= (float)RegionInfo.RegionSizeX) 4359
4166 posX = (float)RegionInfo.RegionSizeX - 0.001f; 4360 else if (posX >= RegionInfo.RegionSizeX)
4361 posX = RegionInfo.RegionSizeX - 0.5f;
4167 if (posY < 0) 4362 if (posY < 0)
4168 posY = 0; 4363 posY = 0;
4169 else if (posY >= (float)RegionInfo.RegionSizeY) 4364 else if (posY >= RegionInfo.RegionSizeY)
4170 posY = (float)RegionInfo.RegionSizeY - 0.001f; 4365 posY = RegionInfo.RegionSizeY - 0.5f;
4171 4366
4172 reason = String.Empty; 4367 reason = String.Empty;
4173 if (Permissions.IsGod(agentID)) 4368 if (Permissions.IsGod(agentID))
@@ -4271,7 +4466,8 @@ namespace OpenSim.Region.Framework.Scenes
4271 { 4466 {
4272 if (RegionInfo.EstateSettings != null) 4467 if (RegionInfo.EstateSettings != null)
4273 { 4468 {
4274 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) 4469 int flags = GetUserFlags(agent.AgentID);
4470 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4275 { 4471 {
4276 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4472 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4277 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4473 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -4460,6 +4656,22 @@ namespace OpenSim.Region.Framework.Scenes
4460 m_log.DebugFormat( 4656 m_log.DebugFormat(
4461 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4657 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4462 4658
4659 if (!LoginsEnabled)
4660 {
4661// reason = "Logins Disabled";
4662 m_log.DebugFormat(
4663 "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName);
4664 return false;
4665 }
4666 // We have to wait until the viewer contacts this region after receiving EAC.
4667 // That calls AddNewClient, which finally creates the ScenePresence
4668 int flags = GetUserFlags(cAgentData.AgentID);
4669 if (RegionInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4670 {
4671 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4672 return false;
4673 }
4674
4463 // TODO: This check should probably be in QueryAccess(). 4675 // TODO: This check should probably be in QueryAccess().
4464 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); 4676 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4465 if (nearestParcel == null) 4677 if (nearestParcel == null)
@@ -4477,8 +4689,14 @@ namespace OpenSim.Region.Framework.Scenes
4477 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. 4689 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4478 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); 4690 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4479 4691
4480 if (sp != null) 4692 if (sp != null)
4481 { 4693 {
4694 if (!sp.IsChildAgent)
4695 {
4696 m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}",
4697 sp.Name, sp.UUID, Name);
4698 return false;
4699 }
4482 if (cAgentData.SessionID != sp.ControllingClient.SessionId) 4700 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4483 { 4701 {
4484 m_log.WarnFormat( 4702 m_log.WarnFormat(
@@ -4563,7 +4781,7 @@ namespace OpenSim.Region.Framework.Scenes
4563 /// <param name='agentID'></param> 4781 /// <param name='agentID'></param>
4564 protected virtual ScenePresence WaitGetScenePresence(UUID agentID) 4782 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
4565 { 4783 {
4566 int ntimes = 20; 4784 int ntimes = 30;
4567 ScenePresence sp = null; 4785 ScenePresence sp = null;
4568 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) 4786 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0))
4569 Thread.Sleep(1000); 4787 Thread.Sleep(1000);
@@ -4613,6 +4831,16 @@ namespace OpenSim.Region.Framework.Scenes
4613 return false; 4831 return false;
4614 } 4832 }
4615 4833
4834// public bool IncomingCloseAgent(UUID agentID)
4835// {
4836// return IncomingCloseAgent(agentID, false);
4837// }
4838
4839// public bool IncomingCloseChildAgent(UUID agentID)
4840// {
4841// return IncomingCloseAgent(agentID, true);
4842// }
4843
4616 /// <summary> 4844 /// <summary>
4617 /// Tell a single client to prepare to close. 4845 /// Tell a single client to prepare to close.
4618 /// </summary> 4846 /// </summary>
@@ -4675,6 +4903,20 @@ namespace OpenSim.Region.Framework.Scenes
4675 4903
4676 if (sp == null) 4904 if (sp == null)
4677 { 4905 {
4906 // If there is no scene presence, we may be handling a dead
4907 // client. These can keep an avatar from reentering a region
4908 // and since they don't get cleaned up they will stick
4909 // around until region restart. So, if there is no SP,
4910 // remove the client as well.
4911 IClientAPI client = null;
4912 if (m_clientManager.TryGetValue(agentID, out client))
4913 {
4914 m_clientManager.Remove(agentID);
4915 if (CapsModule != null)
4916 CapsModule.RemoveCaps(agentID, 0);
4917 m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
4918 return true;
4919 }
4678 m_log.DebugFormat( 4920 m_log.DebugFormat(
4679 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", 4921 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4680 agentID, Name); 4922 agentID, Name);
@@ -4709,7 +4951,11 @@ namespace OpenSim.Region.Framework.Scenes
4709 sp.LifecycleState = ScenePresenceState.Removing; 4951 sp.LifecycleState = ScenePresenceState.Removing;
4710 } 4952 }
4711 4953
4712 sp.ControllingClient.Close(force); 4954 if (sp != null)
4955 {
4956 sp.ControllingClient.Close(force, force);
4957 return true;
4958 }
4713 4959
4714 return true; 4960 return true;
4715 } 4961 }
@@ -4871,7 +5117,10 @@ namespace OpenSim.Region.Framework.Scenes
4871 5117
4872 public LandData GetLandData(float x, float y) 5118 public LandData GetLandData(float x, float y)
4873 { 5119 {
4874 return LandChannel.GetLandObject(x, y).LandData; 5120 ILandObject parcel = LandChannel.GetLandObject(x, y);
5121 if (parcel == null)
5122 return null;
5123 return parcel.LandData;
4875 } 5124 }
4876 5125
4877 /// <summary> 5126 /// <summary>
@@ -4887,7 +5136,10 @@ namespace OpenSim.Region.Framework.Scenes
4887 public LandData GetLandData(uint x, uint y) 5136 public LandData GetLandData(uint x, uint y)
4888 { 5137 {
4889 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 5138 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
4890 return LandChannel.GetLandObject((int)x, (int)y).LandData; 5139 ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y);
5140 if (parcel == null)
5141 return null;
5142 return parcel.LandData;
4891 } 5143 }
4892 5144
4893 #endregion 5145 #endregion
@@ -5275,7 +5527,7 @@ namespace OpenSim.Region.Framework.Scenes
5275 { 5527 {
5276 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 5528 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
5277 { 5529 {
5278 if (grp.RootPart.Expires <= DateTime.Now) 5530 if (grp.GetSittingAvatarsCount() == 0 && grp.RootPart.Expires <= DateTime.Now)
5279 DeleteSceneObject(grp, false); 5531 DeleteSceneObject(grp, false);
5280 } 5532 }
5281 } 5533 }
@@ -5289,35 +5541,80 @@ namespace OpenSim.Region.Framework.Scenes
5289 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); 5541 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID);
5290 } 5542 }
5291 5543
5292 public int GetHealth() 5544 public int GetHealth(out int flags, out string message)
5293 { 5545 {
5294 // Returns: 5546 // Returns:
5295 // 1 = sim is up and accepting http requests. The heartbeat has 5547 // 1 = sim is up and accepting http requests. The heartbeat has
5296 // stopped and the sim is probably locked up, but a remote 5548 // stopped and the sim is probably locked up, but a remote
5297 // admin restart may succeed 5549 // admin restart may succeed
5298 // 5550 //
5299 // 2 = Sim is up and the heartbeat is running. The sim is likely 5551 // 2 = Sim is up and the heartbeat is running. The sim is likely
5300 // usable for people within and logins _may_ work 5552 // usable for people within
5553 //
5554 // 3 = Sim is up and one packet thread is running. Sim is
5555 // unstable and will not accept new logins
5301 // 5556 //
5302 // 3 = We have seen a new user enter within the past 4 minutes 5557 // 4 = Sim is up and both packet threads are running. Sim is
5558 // likely usable
5559 //
5560 // 5 = We have seen a new user enter within the past 4 minutes
5303 // which can be seen as positive confirmation of sim health 5561 // which can be seen as positive confirmation of sim health
5304 // 5562 //
5305 int health = 1; // Start at 1, means we're up 5563 int health = 1; // Start at 1, means we're up
5306 5564
5565 flags = 0;
5566 message = String.Empty;
5567
5568 CheckHeartbeat();
5569
5570 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
5571 {
5572 // We're still starting
5573 // 0 means "in startup", it can't happen another way, since
5574 // to get here, we must be able to accept http connections
5575 return 0;
5576 }
5577
5307 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 5578 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
5308 health += 1; 5579 {
5580 health+=1;
5581 flags |= 1;
5582 }
5583
5584 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
5585 {
5586 health+=1;
5587 flags |= 2;
5588 }
5589
5590 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
5591 {
5592 health+=1;
5593 flags |= 4;
5594 }
5309 else 5595 else
5596 {
5597int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
5598System.Diagnostics.Process proc = new System.Diagnostics.Process();
5599proc.EnableRaisingEvents=false;
5600proc.StartInfo.FileName = "/bin/kill";
5601proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
5602proc.Start();
5603proc.WaitForExit();
5604Thread.Sleep(1000);
5605Environment.Exit(1);
5606 }
5607
5608 if (flags != 7)
5310 return health; 5609 return health;
5311 5610
5312 // A login in the last 4 mins? We can't be doing too badly 5611 // A login in the last 4 mins? We can't be doing too badly
5313 // 5612 //
5314 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 5613 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
5315 health++; 5614 health++;
5316 else 5615 else
5317 return health; 5616 return health;
5318 5617
5319// CheckHeartbeat();
5320
5321 return health; 5618 return health;
5322 } 5619 }
5323 5620
@@ -5405,7 +5702,7 @@ namespace OpenSim.Region.Framework.Scenes
5405 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 5702 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
5406 if (wasUsingPhysics) 5703 if (wasUsingPhysics)
5407 { 5704 {
5408 jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock 5705 jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
5409 } 5706 }
5410 } 5707 }
5411 5708
@@ -5508,14 +5805,14 @@ namespace OpenSim.Region.Framework.Scenes
5508 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5805 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
5509 } 5806 }
5510 5807
5511// private void CheckHeartbeat() 5808 private void CheckHeartbeat()
5512// { 5809 {
5513// if (m_firstHeartbeat) 5810 if (m_firstHeartbeat)
5514// return; 5811 return;
5515// 5812
5516// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5813 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
5517// StartTimer(); 5814 Start();
5518// } 5815 }
5519 5816
5520 public override ISceneObject DeserializeObject(string representation) 5817 public override ISceneObject DeserializeObject(string representation)
5521 { 5818 {
@@ -5572,8 +5869,7 @@ namespace OpenSim.Region.Framework.Scenes
5572 //Go to the edge, this happens in teleporting to a region with no available parcels 5869 //Go to the edge, this happens in teleporting to a region with no available parcels
5573 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); 5870 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
5574 5871
5575 //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); 5872 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
5576
5577 return nearestRegionEdgePoint; 5873 return nearestRegionEdgePoint;
5578 } 5874 }
5579 5875
@@ -5829,7 +6125,55 @@ namespace OpenSim.Region.Framework.Scenes
5829 mapModule.GenerateMaptile(); 6125 mapModule.GenerateMaptile();
5830 } 6126 }
5831 6127
5832 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 6128// public void CleanDroppedAttachments()
6129// {
6130// List<SceneObjectGroup> objectsToDelete =
6131// new List<SceneObjectGroup>();
6132//
6133// lock (m_cleaningAttachments)
6134// {
6135// ForEachSOG(delegate (SceneObjectGroup grp)
6136// {
6137// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
6138// {
6139// UUID agentID = grp.OwnerID;
6140// if (agentID == UUID.Zero)
6141// {
6142// objectsToDelete.Add(grp);
6143// return;
6144// }
6145//
6146// ScenePresence sp = GetScenePresence(agentID);
6147// if (sp == null)
6148// {
6149// objectsToDelete.Add(grp);
6150// return;
6151// }
6152// }
6153// });
6154// }
6155//
6156// foreach (SceneObjectGroup grp in objectsToDelete)
6157// {
6158// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
6159// DeleteSceneObject(grp, true);
6160// }
6161// }
6162
6163 public void ThreadAlive(int threadCode)
6164 {
6165 switch(threadCode)
6166 {
6167 case 1: // Incoming
6168 m_lastIncoming = Util.EnvironmentTickCount();
6169 break;
6170 case 2: // Incoming
6171 m_lastOutgoing = Util.EnvironmentTickCount();
6172 break;
6173 }
6174 }
6175
6176 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5833 { 6177 {
5834 RegenerateMaptile(); 6178 RegenerateMaptile();
5835 6179
@@ -5995,7 +6339,19 @@ namespace OpenSim.Region.Framework.Scenes
5995 return true; 6339 return true;
5996 } 6340 }
5997 6341
5998 /// <summary> 6342 public void StartTimerWatchdog()
6343 {
6344 m_timerWatchdog.Interval = 1000;
6345 m_timerWatchdog.Elapsed += TimerWatchdog;
6346 m_timerWatchdog.AutoReset = true;
6347 m_timerWatchdog.Start();
6348 }
6349
6350 public void TimerWatchdog(object sender, ElapsedEventArgs e)
6351 {
6352 CheckHeartbeat();
6353 }
6354
5999 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 6355 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
6000 /// autopilot that moves an avatar to a sit target!. 6356 /// autopilot that moves an avatar to a sit target!.
6001 /// </summary> 6357 /// </summary>
@@ -6074,6 +6430,11 @@ namespace OpenSim.Region.Framework.Scenes
6074 return m_SpawnPoint - 1; 6430 return m_SpawnPoint - 1;
6075 } 6431 }
6076 6432
6433 private void HandleGcCollect(string module, string[] args)
6434 {
6435 GC.Collect();
6436 }
6437
6077 /// <summary> 6438 /// <summary>
6078 /// Wrappers to get physics modules retrieve assets. 6439 /// Wrappers to get physics modules retrieve assets.
6079 /// </summary> 6440 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 7ff3d40..f420f69 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// If -1 then updates until shutdown. 200 /// If -1 then updates until shutdown.
201 /// </param> 201 /// </param>
202 /// <returns>true if update completed within minimum frame time, false otherwise.</returns> 202 /// <returns>true if update completed within minimum frame time, false otherwise.</returns>
203 public abstract bool Update(int frames); 203 public abstract void Update(int frames);
204 204
205 #endregion 205 #endregion
206 206
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index b9526da..3eefd3c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.Framework.Scenes
66 66
67 private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar) 67 private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
68 { 68 {
69 InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState; 69 InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate)iar.AsyncState;
70 icon.EndInvoke(iar); 70 icon.EndInvoke(iar);
71 } 71 }
72 72
@@ -84,11 +84,11 @@ namespace OpenSim.Region.Framework.Scenes
84 if (neighbourService != null) 84 if (neighbourService != null)
85 neighbour = neighbourService.HelloNeighbour(regionhandle, region); 85 neighbour = neighbourService.HelloNeighbour(regionhandle, region);
86 else 86 else
87 m_log.DebugFormat( "{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name); 87 m_log.DebugFormat("{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name);
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat( "{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up", 91 m_log.DebugFormat("{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up",
92 LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y)); 92 LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
93 93
94 m_scene.EventManager.TriggerOnRegionUp(neighbour); 94 m_scene.EventManager.TriggerOnRegionUp(neighbour);
@@ -114,9 +114,9 @@ namespace OpenSim.Region.Framework.Scenes
114 { 114 {
115 OpenSim.Framework.RegionFlags? regionFlags = n.RegionFlags; 115 OpenSim.Framework.RegionFlags? regionFlags = n.RegionFlags;
116 116
117// m_log.DebugFormat( 117 // m_log.DebugFormat(
118// "{0}: Region flags for {1} as seen by {2} are {3}", 118 // "{0}: Region flags for {1} as seen by {2} are {3}",
119// LogHeader, n.RegionName, m_scene.Name, regionFlags != null ? regionFlags.ToString() : "not present"); 119 // LogHeader, n.RegionName, m_scene.Name, regionFlags != null ? regionFlags.ToString() : "not present");
120 120
121 // Robust services before 2015-01-14 do not return the regionFlags information. In this case, we could 121 // Robust services before 2015-01-14 do not return the regionFlags information. In this case, we could
122 // make a separate RegionFlags call but this would involve a network call for each neighbour. 122 // make a separate RegionFlags call but this would involve a network call for each neighbour.
@@ -132,7 +132,7 @@ namespace OpenSim.Region.Framework.Scenes
132 } 132 }
133 133
134 m_log.DebugFormat( 134 m_log.DebugFormat(
135 "{0} Informing {1} neighbours that region {2} is up", 135 "{0} Informing {1} neighbours that region {2} is up",
136 LogHeader, onlineNeighbours.Count, m_scene.Name); 136 LogHeader, onlineNeighbours.Count, m_scene.Name);
137 137
138 foreach (GridRegion n in onlineNeighbours) 138 foreach (GridRegion n in onlineNeighbours)
@@ -168,15 +168,15 @@ namespace OpenSim.Region.Framework.Scenes
168 168
169 private void SendChildAgentDataUpdateCompleted(IAsyncResult iar) 169 private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
170 { 170 {
171 SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState; 171 SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate)iar.AsyncState;
172 icon.EndInvoke(iar); 172 icon.EndInvoke(iar);
173 } 173 }
174 174
175 public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence) 175 public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence)
176 { 176 {
177// m_log.DebugFormat( 177 // m_log.DebugFormat(
178// "[SCENE COMMUNICATION SERVICE]: Sending child agent position updates for {0} in {1}", 178 // "[SCENE COMMUNICATION SERVICE]: Sending child agent position updates for {0} in {1}",
179// presence.Name, m_scene.Name); 179 // presence.Name, m_scene.Name);
180 180
181 // This assumes that we know what our neighbors are. 181 // This assumes that we know what our neighbors are.
182 try 182 try
@@ -218,8 +218,11 @@ namespace OpenSim.Region.Framework.Scenes
218 } 218 }
219 } 219 }
220 220
221 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
222
221 /// <summary> 223 /// <summary>
222 /// Closes a child agent on a given region 224 /// This Closes child agents on neighboring regions
225 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
223 /// </summary> 226 /// </summary>
224 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token) 227 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
225 { 228 {
@@ -231,6 +234,13 @@ namespace OpenSim.Region.Framework.Scenes
231 234
232 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 235 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
233 236
237 if (destination == null)
238 {
239 m_log.DebugFormat(
240 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} FAIL, region with handle {1} not found", agentID, regionHandle);
241 return;
242 }
243
234 m_log.DebugFormat( 244 m_log.DebugFormat(
235 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName); 245 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
236 246
@@ -245,21 +255,22 @@ namespace OpenSim.Region.Framework.Scenes
245 /// <param name="regionslst"></param> 255 /// <param name="regionslst"></param>
246 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst) 256 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
247 { 257 {
248 foreach (ulong handle in regionslst) 258 if (regionslst.Count == 0)
259 return;
260
261 // use a single thread job for all
262 Util.FireAndForget(o =>
249 { 263 {
250 // We must take a copy here since handle is acts like a reference when used in an iterator. 264 foreach (ulong handle in regionslst)
251 // This leads to race conditions if directly passed to SendCloseChildAgent with more than one neighbour region. 265 {
252 ulong handleCopy = handle; 266 SendCloseChildAgent(agentID, handle, auth_code);
253 Util.FireAndForget( 267 }
254 o => SendCloseChildAgent(agentID, handleCopy, auth_code), 268 }, null, "SceneCommunicationService.SendCloseChildAgentConnections");
255 null,
256 "SceneCommunicationService.SendCloseChildAgentConnections");
257 }
258 } 269 }
259 270
260 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 271 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
261 { 272 {
262 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 273 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
263 } 274 }
264 } 275 }
265} \ No newline at end of file 276}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e0080f2..0879cce 100755
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -134,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes
134 144
135 protected internal void Close() 145 protected internal void Close()
136 { 146 {
137 lock (m_presenceLock) 147 m_scenePresencesLock.EnterWriteLock();
148 try
138 { 149 {
139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 150 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
140 List<ScenePresence> newlist = new List<ScenePresence>(); 151 List<ScenePresence> newlist = new List<ScenePresence>();
141 m_scenePresenceMap = newmap; 152 m_scenePresenceMap = newmap;
142 m_scenePresenceArray = newlist; 153 m_scenePresenceArray = newlist;
143 } 154 }
155 finally
156 {
157 m_scenePresencesLock.ExitWriteLock();
158 }
144 159
145 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
146 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
@@ -207,6 +222,12 @@ namespace OpenSim.Region.Framework.Scenes
207 return PhysicsScene.Simulate((float)elapsed); 222 return PhysicsScene.Simulate((float)elapsed);
208 } 223 }
209 224
225 protected internal void ProcessPhysicsPreSimulation()
226 {
227 if(PhysicsScene != null)
228 PhysicsScene.ProcessPreSimulation();
229 }
230
210 protected internal void UpdateScenePresenceMovement() 231 protected internal void UpdateScenePresenceMovement()
211 { 232 {
212 ForEachScenePresence(delegate(ScenePresence presence) 233 ForEachScenePresence(delegate(ScenePresence presence)
@@ -261,13 +282,54 @@ namespace OpenSim.Region.Framework.Scenes
261 protected internal bool AddRestoredSceneObject( 282 protected internal bool AddRestoredSceneObject(
262 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 283 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
263 { 284 {
285 if (!m_parentScene.CombineRegions)
286 {
287 // temporary checks to remove after varsize suport
288 float regionSizeX = m_parentScene.RegionInfo.RegionSizeX;
289 if (regionSizeX == 0)
290 regionSizeX = Constants.RegionSize;
291 float regionSizeY = m_parentScene.RegionInfo.RegionSizeY;
292 if (regionSizeY == 0)
293 regionSizeY = Constants.RegionSize;
294
295 // KF: Check for out-of-region, move inside and make static.
296 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
297 sceneObject.RootPart.GroupPosition.Y,
298 sceneObject.RootPart.GroupPosition.Z);
299 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
300 npos.X > regionSizeX ||
301 npos.Y > regionSizeY))
302 {
303 if (npos.X < 0.0) npos.X = 1.0f;
304 if (npos.Y < 0.0) npos.Y = 1.0f;
305 if (npos.Z < 0.0) npos.Z = 0.0f;
306 if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f;
307 if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f;
308
309 SceneObjectPart rootpart = sceneObject.RootPart;
310 rootpart.GroupPosition = npos;
311
312 foreach (SceneObjectPart part in sceneObject.Parts)
313 {
314 if (part == rootpart)
315 continue;
316 part.GroupPosition = npos;
317 }
318 rootpart.Velocity = Vector3.Zero;
319 rootpart.AngularVelocity = Vector3.Zero;
320 rootpart.Acceleration = Vector3.Zero;
321 }
322 }
323
324 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
325
264 if (attachToBackup && (!alreadyPersisted)) 326 if (attachToBackup && (!alreadyPersisted))
265 { 327 {
266 sceneObject.ForceInventoryPersistence(); 328 sceneObject.ForceInventoryPersistence();
267 sceneObject.HasGroupChanged = true; 329 sceneObject.HasGroupChanged = true;
268 } 330 }
269 331
270 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 332 return ret;
271 } 333 }
272 334
273 /// <summary> 335 /// <summary>
@@ -284,12 +346,16 @@ namespace OpenSim.Region.Framework.Scenes
284 /// </returns> 346 /// </returns>
285 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 347 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
286 { 348 {
287 // Ensure that we persist this new scene object if it's not an 349
350 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
351
352 // Ensure that we persist this new scene object if it's not an
288 // attachment 353 // attachment
354
289 if (attachToBackup) 355 if (attachToBackup)
290 sceneObject.HasGroupChanged = true; 356 sceneObject.HasGroupChanged = true;
291 357
292 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 358 return ret;
293 } 359 }
294 360
295 /// <summary> 361 /// <summary>
@@ -324,9 +390,8 @@ namespace OpenSim.Region.Framework.Scenes
324 if (pa != null && pa.IsPhysical && vel != Vector3.Zero) 390 if (pa != null && pa.IsPhysical && vel != Vector3.Zero)
325 { 391 {
326 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); 392 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
327 sceneObject.Velocity = vel;
328 } 393 }
329 394
330 return true; 395 return true;
331 } 396 }
332 397
@@ -351,6 +416,11 @@ namespace OpenSim.Region.Framework.Scenes
351 /// </returns> 416 /// </returns>
352 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 417 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
353 { 418 {
419 if (sceneObject == null)
420 {
421 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
422 return false;
423 }
354 if (sceneObject.UUID == UUID.Zero) 424 if (sceneObject.UUID == UUID.Zero)
355 { 425 {
356 m_log.ErrorFormat( 426 m_log.ErrorFormat(
@@ -383,9 +453,9 @@ namespace OpenSim.Region.Framework.Scenes
383 { 453 {
384 Vector3 scale = part.Shape.Scale; 454 Vector3 scale = part.Shape.Scale;
385 455
386 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); 456 scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
387 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); 457 scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
388 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); 458 scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
389 459
390 part.Shape.Scale = scale; 460 part.Shape.Scale = scale;
391 } 461 }
@@ -406,36 +476,39 @@ namespace OpenSim.Region.Framework.Scenes
406 476
407 sceneObject.AttachToScene(m_parentScene); 477 sceneObject.AttachToScene(m_parentScene);
408 478
409 if (sendClientUpdates)
410 sceneObject.ScheduleGroupForFullUpdate();
411
412 Entities.Add(sceneObject); 479 Entities.Add(sceneObject);
413 480
414 if (attachToBackup)
415 sceneObject.AttachToBackup();
416
417 lock (SceneObjectGroupsByFullID) 481 lock (SceneObjectGroupsByFullID)
418 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 482 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
419 483
420 lock (SceneObjectGroupsByFullPartID) 484 foreach (SceneObjectPart part in parts)
421 { 485 {
422 foreach (SceneObjectPart part in parts) 486 lock (SceneObjectGroupsByFullPartID)
423 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 487 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
424 }
425
426 lock (SceneObjectGroupsByLocalPartID)
427 {
428// m_log.DebugFormat(
429// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
430// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
431 488
432 foreach (SceneObjectPart part in parts) 489 lock (SceneObjectGroupsByLocalPartID)
433 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; 490 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
434 } 491 }
435 492
493 if (sendClientUpdates)
494 sceneObject.ScheduleGroupForFullUpdate();
495
496 if (attachToBackup)
497 sceneObject.AttachToBackup();
498
436 return true; 499 return true;
437 } 500 }
438 501
502 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
503 {
504 // no tests, caller has responsability...
505 lock (SceneObjectGroupsByFullPartID)
506 SceneObjectGroupsByFullPartID[part.UUID] = grp;
507
508 lock (SceneObjectGroupsByLocalPartID)
509 SceneObjectGroupsByLocalPartID[part.LocalId] = grp;
510 }
511
439 /// <summary> 512 /// <summary>
440 /// Delete an object from the scene 513 /// Delete an object from the scene
441 /// </summary> 514 /// </summary>
@@ -476,25 +549,23 @@ namespace OpenSim.Region.Framework.Scenes
476 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 549 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
477 RemovePhysicalPrim(grp.PrimCount); 550 RemovePhysicalPrim(grp.PrimCount);
478 } 551 }
479 552
553 bool ret = Entities.Remove(uuid);
554
480 lock (SceneObjectGroupsByFullID) 555 lock (SceneObjectGroupsByFullID)
481 SceneObjectGroupsByFullID.Remove(grp.UUID); 556 SceneObjectGroupsByFullID.Remove(grp.UUID);
482 557
483 lock (SceneObjectGroupsByFullPartID) 558 SceneObjectPart[] parts = grp.Parts;
559 for (int i = 0; i < parts.Length; i++)
484 { 560 {
485 SceneObjectPart[] parts = grp.Parts; 561 lock (SceneObjectGroupsByFullPartID)
486 for (int i = 0; i < parts.Length; i++)
487 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 562 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
488 }
489 563
490 lock (SceneObjectGroupsByLocalPartID) 564 lock (SceneObjectGroupsByLocalPartID)
491 {
492 SceneObjectPart[] parts = grp.Parts;
493 for (int i = 0; i < parts.Length; i++)
494 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 565 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
495 } 566 }
496 567
497 return Entities.Remove(uuid); 568 return ret;
498 } 569 }
499 570
500 /// <summary> 571 /// <summary>
@@ -509,6 +580,30 @@ namespace OpenSim.Region.Framework.Scenes
509 m_updateList[obj.UUID] = obj; 580 m_updateList[obj.UUID] = obj;
510 } 581 }
511 582
583 public void FireAttachToBackup(SceneObjectGroup obj)
584 {
585 if (OnAttachToBackup != null)
586 {
587 OnAttachToBackup(obj);
588 }
589 }
590
591 public void FireDetachFromBackup(SceneObjectGroup obj)
592 {
593 if (OnDetachFromBackup != null)
594 {
595 OnDetachFromBackup(obj);
596 }
597 }
598
599 public void FireChangeBackup(SceneObjectGroup obj)
600 {
601 if (OnChangeBackup != null)
602 {
603 OnChangeBackup(obj);
604 }
605 }
606
512 /// <summary> 607 /// <summary>
513 /// Process all pending updates 608 /// Process all pending updates
514 /// </summary> 609 /// </summary>
@@ -600,7 +695,8 @@ namespace OpenSim.Region.Framework.Scenes
600 695
601 Entities[presence.UUID] = presence; 696 Entities[presence.UUID] = presence;
602 697
603 lock (m_presenceLock) 698 m_scenePresencesLock.EnterWriteLock();
699 try
604 { 700 {
605 m_numChildAgents++; 701 m_numChildAgents++;
606 702
@@ -626,6 +722,10 @@ namespace OpenSim.Region.Framework.Scenes
626 m_scenePresenceMap = newmap; 722 m_scenePresenceMap = newmap;
627 m_scenePresenceArray = newlist; 723 m_scenePresenceArray = newlist;
628 } 724 }
725 finally
726 {
727 m_scenePresencesLock.ExitWriteLock();
728 }
629 729
630 return presence; 730 return presence;
631 } 731 }
@@ -642,7 +742,8 @@ namespace OpenSim.Region.Framework.Scenes
642 agentID); 742 agentID);
643 } 743 }
644 744
645 lock (m_presenceLock) 745 m_scenePresencesLock.EnterWriteLock();
746 try
646 { 747 {
647 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 748 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
648 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 749 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -664,6 +765,10 @@ namespace OpenSim.Region.Framework.Scenes
664 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 765 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
665 } 766 }
666 } 767 }
768 finally
769 {
770 m_scenePresencesLock.ExitWriteLock();
771 }
667 } 772 }
668 773
669 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 774 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -892,7 +997,7 @@ namespace OpenSim.Region.Framework.Scenes
892 m_log.WarnFormat( 997 m_log.WarnFormat(
893 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", 998 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.",
894 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); 999 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
895 1000 m_log.WarnFormat("stack: {0}", Environment.StackTrace);
896 SceneObjectGroupsByLocalPartID.Remove(localID); 1001 SceneObjectGroupsByLocalPartID.Remove(localID);
897 } 1002 }
898 } 1003 }
@@ -1228,6 +1333,52 @@ namespace OpenSim.Region.Framework.Scenes
1228 1333
1229 #region Client Event handlers 1334 #region Client Event handlers
1230 1335
1336 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1337 {
1338 SceneObjectPart part = GetSceneObjectPart(localID);
1339 ObjectChangeData data = (ObjectChangeData)odata;
1340
1341 if (part != null)
1342 {
1343 SceneObjectGroup grp = part.ParentGroup;
1344 if (grp != null)
1345 {
1346 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1347 {
1348 // These two are exceptions SL makes in the interpretation
1349 // of the change flags. Must check them here because otherwise
1350 // the group flag (see below) would be lost
1351 if (data.change == ObjectChangeType.groupS)
1352 data.change = ObjectChangeType.primS;
1353 if (data.change == ObjectChangeType.groupPS)
1354 data.change = ObjectChangeType.primPS;
1355 part.StoreUndoState(data.change); // lets test only saving what we changed
1356 grp.doChangeObject(part, (ObjectChangeData)data);
1357 }
1358 else
1359 {
1360 // Is this any kind of group operation?
1361 if ((data.change & ObjectChangeType.Group) != 0)
1362 {
1363 // Is a move and/or rotation requested?
1364 if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
1365 {
1366 // Are we allowed to move it?
1367 if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId))
1368 {
1369 // Strip all but move and rotation from request
1370 data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
1371
1372 part.StoreUndoState(data.change);
1373 grp.doChangeObject(part, (ObjectChangeData)data);
1374 }
1375 }
1376 }
1377 }
1378 }
1379 }
1380 }
1381
1231 /// <summary> 1382 /// <summary>
1232 /// Update the scale of an individual prim. 1383 /// Update the scale of an individual prim.
1233 /// </summary> 1384 /// </summary>
@@ -1242,7 +1393,17 @@ namespace OpenSim.Region.Framework.Scenes
1242 { 1393 {
1243 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1394 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1244 { 1395 {
1396 bool physbuild = false;
1397 if (part.ParentGroup.RootPart.PhysActor != null)
1398 {
1399 part.ParentGroup.RootPart.PhysActor.Building = true;
1400 physbuild = true;
1401 }
1402
1245 part.Resize(scale); 1403 part.Resize(scale);
1404
1405 if (physbuild)
1406 part.ParentGroup.RootPart.PhysActor.Building = false;
1246 } 1407 }
1247 } 1408 }
1248 } 1409 }
@@ -1254,7 +1415,17 @@ namespace OpenSim.Region.Framework.Scenes
1254 { 1415 {
1255 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1416 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1256 { 1417 {
1418 bool physbuild = false;
1419 if (group.RootPart.PhysActor != null)
1420 {
1421 group.RootPart.PhysActor.Building = true;
1422 physbuild = true;
1423 }
1424
1257 group.GroupResize(scale); 1425 group.GroupResize(scale);
1426
1427 if (physbuild)
1428 group.RootPart.PhysActor.Building = false;
1258 } 1429 }
1259 } 1430 }
1260 } 1431 }
@@ -1393,8 +1564,13 @@ namespace OpenSim.Region.Framework.Scenes
1393 { 1564 {
1394 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1565 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1395 { 1566 {
1396 if (m_parentScene.AttachmentsModule != null) 1567 // Set the new attachment point data in the object
1397 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1568 byte attachmentPoint = group.GetAttachmentPoint();
1569 group.UpdateGroupPosition(pos);
1570 group.IsAttachment = false;
1571 group.AbsolutePosition = group.RootPart.AttachedPos;
1572 group.AttachmentPoint = attachmentPoint;
1573 group.HasGroupChanged = true;
1398 } 1574 }
1399 else 1575 else
1400 { 1576 {
@@ -1452,6 +1628,7 @@ namespace OpenSim.Region.Framework.Scenes
1452 // VolumeDetect can't be set via UI and will always be off when a change is made there 1628 // VolumeDetect can't be set via UI and will always be off when a change is made there
1453 // now only change volume dtc if phantom off 1629 // now only change volume dtc if phantom off
1454 1630
1631 bool wantedPhys = UsePhysics;
1455 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data 1632 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1456 { 1633 {
1457 bool vdtc; 1634 bool vdtc;
@@ -1468,10 +1645,17 @@ namespace OpenSim.Region.Framework.Scenes
1468 if (part != null) 1645 if (part != null)
1469 { 1646 {
1470 part.UpdateExtraPhysics(PhysData); 1647 part.UpdateExtraPhysics(PhysData);
1471 if (part.UpdatePhysRequired) 1648 if (part.UpdatePhysRequired && remoteClient != null)
1472 remoteClient.SendPartPhysicsProprieties(part); 1649 remoteClient.SendPartPhysicsProprieties(part);
1473 } 1650 }
1474 } 1651 }
1652
1653 if (wantedPhys != group.UsesPhysics && remoteClient != null)
1654 {
1655 remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " +
1656 m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None");
1657 group.RootPart.ScheduleFullUpdate();
1658 }
1475 } 1659 }
1476 } 1660 }
1477 } 1661 }
@@ -1616,6 +1800,7 @@ namespace OpenSim.Region.Framework.Scenes
1616 { 1800 {
1617 part.Material = Convert.ToByte(material); 1801 part.Material = Convert.ToByte(material);
1618 group.HasGroupChanged = true; 1802 group.HasGroupChanged = true;
1803 remoteClient.SendPartPhysicsProprieties(part);
1619 } 1804 }
1620 } 1805 }
1621 } 1806 }
@@ -1694,12 +1879,14 @@ namespace OpenSim.Region.Framework.Scenes
1694 return; 1879 return;
1695 1880
1696 Monitor.Enter(m_updateLock); 1881 Monitor.Enter(m_updateLock);
1882
1697 try 1883 try
1698 { 1884 {
1885
1699 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1886 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1700 1887
1701 // We do this in reverse to get the link order of the prims correct 1888 // We do this in reverse to get the link order of the prims correct
1702 for (int i = 0 ; i < children.Count ; i++) 1889 for (int i = 0; i < children.Count; i++)
1703 { 1890 {
1704 SceneObjectGroup child = children[i].ParentGroup; 1891 SceneObjectGroup child = children[i].ParentGroup;
1705 1892
@@ -1710,9 +1897,13 @@ namespace OpenSim.Region.Framework.Scenes
1710 // Make sure no child prim is set for sale 1897 // Make sure no child prim is set for sale
1711 // So that, on delink, no prims are unwittingly 1898 // So that, on delink, no prims are unwittingly
1712 // left for sale and sold off 1899 // left for sale and sold off
1713 child.RootPart.ObjectSaleType = 0; 1900
1714 child.RootPart.SalePrice = 10; 1901 if (child != null)
1715 childGroups.Add(child); 1902 {
1903 child.RootPart.ObjectSaleType = 0;
1904 child.RootPart.SalePrice = 10;
1905 childGroups.Add(child);
1906 }
1716 } 1907 }
1717 1908
1718 foreach (SceneObjectGroup child in childGroups) 1909 foreach (SceneObjectGroup child in childGroups)
@@ -1741,6 +1932,17 @@ namespace OpenSim.Region.Framework.Scenes
1741 } 1932 }
1742 finally 1933 finally
1743 { 1934 {
1935/*
1936 lock (SceneObjectGroupsByLocalPartID)
1937 {
1938 foreach (SceneObjectPart part in parentGroup.Parts)
1939 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1940 }
1941*/
1942 parentGroup.AdjustChildPrimPermissions(false);
1943 parentGroup.HasGroupChanged = true;
1944 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1945 parentGroup.ScheduleGroupForFullUpdate();
1744 Monitor.Exit(m_updateLock); 1946 Monitor.Exit(m_updateLock);
1745 } 1947 }
1746 } 1948 }
@@ -1782,21 +1984,23 @@ namespace OpenSim.Region.Framework.Scenes
1782 1984
1783 SceneObjectGroup group = part.ParentGroup; 1985 SceneObjectGroup group = part.ParentGroup;
1784 if (!affectedGroups.Contains(group)) 1986 if (!affectedGroups.Contains(group))
1987 {
1785 affectedGroups.Add(group); 1988 affectedGroups.Add(group);
1989 }
1786 } 1990 }
1787 } 1991 }
1788 } 1992 }
1789 1993
1790 foreach (SceneObjectPart child in childParts) 1994 if (childParts.Count > 0)
1791 { 1995 {
1792 // Unlink all child parts from their groups 1996 foreach (SceneObjectPart child in childParts)
1793 // 1997 {
1794 child.ParentGroup.DelinkFromGroup(child, true); 1998 // Unlink all child parts from their groups
1795 1999 //
1796 // These are not in affected groups and will not be 2000 child.ParentGroup.DelinkFromGroup(child, true);
1797 // handled further. Do the honors here. 2001 child.ParentGroup.HasGroupChanged = true;
1798 child.ParentGroup.HasGroupChanged = true; 2002 child.ParentGroup.ScheduleGroupForFullUpdate();
1799 child.ParentGroup.ScheduleGroupForFullUpdate(); 2003 }
1800 } 2004 }
1801 2005
1802 foreach (SceneObjectPart root in rootParts) 2006 foreach (SceneObjectPart root in rootParts)
@@ -1810,52 +2014,58 @@ namespace OpenSim.Region.Framework.Scenes
1810 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 2014 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1811 int numChildren = newSet.Count; 2015 int numChildren = newSet.Count;
1812 2016
2017 if (numChildren == 1)
2018 break;
2019
1813 // If there are prims left in a link set, but the root is 2020 // If there are prims left in a link set, but the root is
1814 // slated for unlink, we need to do this 2021 // slated for unlink, we need to do this
2022 // Unlink the remaining set
1815 // 2023 //
1816 if (numChildren != 1) 2024 bool sendEventsToRemainder = false;
1817 { 2025 if (numChildren == 2) // only one child prim no re-link needed
1818 // Unlink the remaining set 2026 sendEventsToRemainder = true;
1819 //
1820 bool sendEventsToRemainder = true;
1821 if (numChildren > 1)
1822 sendEventsToRemainder = false;
1823 2027
1824 foreach (SceneObjectPart p in newSet) 2028 foreach (SceneObjectPart p in newSet)
2029 {
2030 if (p != group.RootPart)
1825 { 2031 {
1826 if (p != group.RootPart) 2032 group.DelinkFromGroup(p, sendEventsToRemainder);
1827 group.DelinkFromGroup(p, sendEventsToRemainder); 2033 if (sendEventsToRemainder) // finish single child prim now
2034 {
2035 p.ParentGroup.HasGroupChanged = true;
2036 p.ParentGroup.ScheduleGroupForFullUpdate();
2037 }
1828 } 2038 }
2039 }
2040
2041 // If there is more than one prim remaining, we
2042 // need to re-link
2043 //
2044 if (numChildren > 2)
2045 {
2046 // Remove old root
2047 //
2048 if (newSet.Contains(root))
2049 newSet.Remove(root);
1829 2050
1830 // If there is more than one prim remaining, we 2051 // Preserve link ordering
1831 // need to re-link
1832 // 2052 //
1833 if (numChildren > 2) 2053 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1834 { 2054 {
1835 // Remove old root 2055 return a.LinkNum.CompareTo(b.LinkNum);
1836 // 2056 });
1837 if (newSet.Contains(root))
1838 newSet.Remove(root);
1839
1840 // Preserve link ordering
1841 //
1842 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1843 {
1844 return a.LinkNum.CompareTo(b.LinkNum);
1845 });
1846 2057
1847 // Determine new root 2058 // Determine new root
1848 // 2059 //
1849 SceneObjectPart newRoot = newSet[0]; 2060 SceneObjectPart newRoot = newSet[0];
1850 newSet.RemoveAt(0); 2061 newSet.RemoveAt(0);
1851 2062
1852 foreach (SceneObjectPart newChild in newSet) 2063 foreach (SceneObjectPart newChild in newSet)
1853 newChild.ClearUpdateSchedule(); 2064 newChild.ClearUpdateSchedule();
1854 2065
1855 LinkObjects(newRoot, newSet); 2066 LinkObjects(newRoot, newSet);
1856 if (!affectedGroups.Contains(newRoot.ParentGroup)) 2067// if (!affectedGroups.Contains(newRoot.ParentGroup))
1857 affectedGroups.Add(newRoot.ParentGroup); 2068// affectedGroups.Add(newRoot.ParentGroup);
1858 }
1859 } 2069 }
1860 } 2070 }
1861 2071
@@ -1863,6 +2073,12 @@ namespace OpenSim.Region.Framework.Scenes
1863 // 2073 //
1864 foreach (SceneObjectGroup g in affectedGroups) 2074 foreach (SceneObjectGroup g in affectedGroups)
1865 { 2075 {
2076 // Child prims that have been unlinked and deleted will
2077 // return unless the root is deleted. This will remove them
2078 // from the database. They will be rewritten immediately,
2079 // minus the rows for the unlinked child prims.
2080 g.AdjustChildPrimPermissions(false);
2081 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1866 g.TriggerScriptChangedEvent(Changed.LINK); 2082 g.TriggerScriptChangedEvent(Changed.LINK);
1867 g.HasGroupChanged = true; // Persist 2083 g.HasGroupChanged = true; // Persist
1868 g.ScheduleGroupForFullUpdate(); 2084 g.ScheduleGroupForFullUpdate();
@@ -1936,120 +2152,90 @@ namespace OpenSim.Region.Framework.Scenes
1936 /// <param name="GroupID"></param> 2152 /// <param name="GroupID"></param>
1937 /// <param name="rot"></param> 2153 /// <param name="rot"></param>
1938 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2154 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1939 public SceneObjectGroup DuplicateObject( 2155 /// <summary>
1940 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2156 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1941 { 2157 {
1942 Monitor.Enter(m_updateLock); 2158// m_log.DebugFormat(
2159// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2160// originalPrimID, offset, AgentID);
1943 2161
1944 try 2162 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2163 if (original != null)
1945 { 2164 {
1946 // m_log.DebugFormat( 2165 if (m_parentScene.Permissions.CanDuplicateObject(
1947 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
1948 // originalPrimID, offset, AgentID);
1949
1950 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1951 if (original == null)
1952 {
1953 m_log.WarnFormat(
1954 "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID);
1955
1956 return null;
1957 }
1958
1959 if (!m_parentScene.Permissions.CanDuplicateObject(
1960 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) 2166 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1961 return null;
1962
1963 SceneObjectGroup copy = original.Copy(true);
1964 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1965
1966 if (original.OwnerID != AgentID)
1967 { 2167 {
1968 copy.SetOwnerId(AgentID); 2168 SceneObjectGroup copy = original.Copy(true);
1969 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); 2169 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1970
1971 SceneObjectPart[] partList = copy.Parts;
1972 2170
1973 if (m_parentScene.Permissions.PropagatePermissions()) 2171 if (original.OwnerID != AgentID)
1974 { 2172 {
1975 foreach (SceneObjectPart child in partList) 2173 copy.SetOwnerId(AgentID);
2174 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
2175
2176 SceneObjectPart[] partList = copy.Parts;
2177
2178 if (m_parentScene.Permissions.PropagatePermissions())
1976 { 2179 {
1977 child.Inventory.ChangeInventoryOwner(AgentID); 2180 foreach (SceneObjectPart child in partList)
1978 child.TriggerScriptChangedEvent(Changed.OWNER); 2181 {
1979 child.ApplyNextOwnerPermissions(); 2182 child.Inventory.ChangeInventoryOwner(AgentID);
2183 child.TriggerScriptChangedEvent(Changed.OWNER);
2184 child.ApplyNextOwnerPermissions();
2185 }
1980 } 2186 }
1981 } 2187 }
1982 2188
1983 copy.RootPart.ObjectSaleType = 0; 2189 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1984 copy.RootPart.SalePrice = 10; 2190 Entities.Add(copy);
1985 }
1986 2191
1987 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2192 lock (SceneObjectGroupsByFullID)
1988 Entities.Add(copy); 2193 SceneObjectGroupsByFullID[copy.UUID] = copy;
1989
1990 lock (SceneObjectGroupsByFullID)
1991 SceneObjectGroupsByFullID[copy.UUID] = copy;
1992
1993 SceneObjectPart[] children = copy.Parts;
1994
1995 lock (SceneObjectGroupsByFullPartID)
1996 {
1997 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1998 foreach (SceneObjectPart part in children)
1999 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2000 }
2001
2002 lock (SceneObjectGroupsByLocalPartID)
2003 {
2004 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2005 foreach (SceneObjectPart part in children)
2006 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2007 }
2008 // PROBABLE END OF FIXME
2009 2194
2010 // Since we copy from a source group that is in selected 2195 SceneObjectPart[] parts = copy.Parts;
2011 // state, but the copy is shown deselected in the viewer, 2196 foreach (SceneObjectPart part in parts)
2012 // We need to clear the selection flag here, else that 2197 {
2013 // prim never gets persisted at all. The client doesn't 2198 lock (SceneObjectGroupsByFullPartID)
2014 // think it's selected, so it will never send a deselect... 2199 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2015 copy.IsSelected = false; 2200 lock (SceneObjectGroupsByLocalPartID)
2201 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2202 }
2016 2203
2017 m_numTotalPrim += copy.Parts.Length; 2204 // PROBABLE END OF FIXME
2018 2205
2019 // Go through all parts (primitives and meshes) of this Scene Object 2206 // Since we copy from a source group that is in selected
2020 foreach (SceneObjectPart part in copy.Parts) 2207 // state, but the copy is shown deselected in the viewer,
2021 { 2208 // We need to clear the selection flag here, else that
2022 // Keep track of the total number of meshes or geometric primitives now in the scene; 2209 // prim never gets persisted at all. The client doesn't
2023 // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to 2210 // think it's selected, so it will never send a deselect...
2024 // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives 2211 copy.IsSelected = false;
2025 if (part.GetPrimType() == PrimType.SCULPT)
2026 m_numMesh++;
2027 else
2028 m_numPrim++;
2029 }
2030 2212
2031 if (rot != Quaternion.Identity) 2213 m_numPrim += copy.Parts.Length;
2032 {
2033 copy.UpdateGroupRotationR(rot);
2034 }
2035 2214
2036 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2215 if (rot != Quaternion.Identity)
2037 copy.HasGroupChanged = true; 2216 {
2038 copy.ScheduleGroupForFullUpdate(); 2217 copy.UpdateGroupRotationR(rot);
2039 copy.ResumeScripts(); 2218 }
2219
2220 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
2221 copy.HasGroupChanged = true;
2222 copy.ScheduleGroupForFullUpdate();
2223 copy.ResumeScripts();
2040 2224
2041 // required for physics to update it's position 2225 // required for physics to update it's position
2042 copy.AbsolutePosition = copy.AbsolutePosition; 2226 copy.AbsolutePosition = copy.AbsolutePosition;
2043 2227
2044 return copy; 2228 return copy;
2229 }
2045 } 2230 }
2046 finally 2231 else
2047 { 2232 {
2048 Monitor.Exit(m_updateLock); 2233 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
2049 } 2234 }
2235
2236 return null;
2050 } 2237 }
2051 2238
2052 /// <summary>
2053 /// Calculates the distance between two Vector3s 2239 /// Calculates the distance between two Vector3s
2054 /// </summary> 2240 /// </summary>
2055 /// <param name="v1"></param> 2241 /// <param name="v1"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index 28f7896..c5c083a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -99,11 +99,11 @@ namespace OpenSim.Region.Framework.Scenes
99 } 99 }
100 } 100 }
101 101
102 private readonly List<Scene> m_localScenes = new List<Scene>(); 102 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>();
103 103
104 public List<Scene> Scenes 104 public List<Scene> Scenes
105 { 105 {
106 get { return new List<Scene>(m_localScenes); } 106 get { return new List<Scene>(m_localScenes.FindAll(delegate(Scene s) { return true; })); }
107 } 107 }
108 108
109 /// <summary> 109 /// <summary>
@@ -120,13 +120,10 @@ namespace OpenSim.Region.Framework.Scenes
120 { 120 {
121 if (CurrentScene == null) 121 if (CurrentScene == null)
122 { 122 {
123 lock (m_localScenes) 123 List<Scene> sceneList = Scenes;
124 { 124 if (sceneList.Count == 0)
125 if (m_localScenes.Count > 0) 125 return null;
126 return m_localScenes[0]; 126 return sceneList[0];
127 else
128 return null;
129 }
130 } 127 }
131 else 128 else
132 { 129 {
@@ -138,41 +135,35 @@ namespace OpenSim.Region.Framework.Scenes
138 public SceneManager() 135 public SceneManager()
139 { 136 {
140 m_instance = this; 137 m_instance = this;
141 m_localScenes = new List<Scene>(); 138 m_localScenes = new DoubleDictionary<UUID, string, Scene>();
142 } 139 }
143 140
144 public void Close() 141 public void Close()
145 { 142 {
143 List<Scene> localScenes = null;
144
146 lock (m_localScenes) 145 lock (m_localScenes)
147 { 146 {
148 for (int i = 0; i < m_localScenes.Count; i++) 147 localScenes = Scenes;
149 { 148 }
150 m_localScenes[i].Close(); 149
151 } 150 for (int i = 0; i < localScenes.Count; i++)
151 {
152 localScenes[i].Close();
152 } 153 }
153 } 154 }
154 155
155 public void Close(Scene cscene) 156 public void Close(Scene cscene)
156 { 157 {
157 lock (m_localScenes) 158 if (!m_localScenes.ContainsKey(cscene.RegionInfo.RegionID))
158 { 159 return;
159 if (m_localScenes.Contains(cscene)) 160 cscene.Close();
160 {
161 for (int i = 0; i < m_localScenes.Count; i++)
162 {
163 if (m_localScenes[i].Equals(cscene))
164 {
165 m_localScenes[i].Close();
166 }
167 }
168 }
169 }
170 } 161 }
171 162
172 public void Add(Scene scene) 163 public void Add(Scene scene)
173 { 164 {
174 lock (m_localScenes) 165 lock (m_localScenes)
175 m_localScenes.Add(scene); 166 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
176 167
177 scene.OnRestart += HandleRestart; 168 scene.OnRestart += HandleRestart;
178 scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange; 169 scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange;
@@ -184,15 +175,8 @@ namespace OpenSim.Region.Framework.Scenes
184 175
185 lock (m_localScenes) 176 lock (m_localScenes)
186 { 177 {
187 for (int i = 0; i < m_localScenes.Count; i++) 178 m_localScenes.TryGetValue(rdata.RegionID, out restartedScene);
188 { 179 m_localScenes.Remove(rdata.RegionID);
189 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
190 {
191 restartedScene = m_localScenes[i];
192 m_localScenes.RemoveAt(i);
193 break;
194 }
195 }
196 } 180 }
197 181
198 // If the currently selected scene has been restarted, then we can't reselect here since we the scene 182 // If the currently selected scene has been restarted, then we can't reselect here since we the scene
@@ -207,39 +191,36 @@ namespace OpenSim.Region.Framework.Scenes
207 private void HandleRegionReadyStatusChange(IScene scene) 191 private void HandleRegionReadyStatusChange(IScene scene)
208 { 192 {
209 lock (m_localScenes) 193 lock (m_localScenes)
210 AllRegionsReady = m_localScenes.TrueForAll(s => s.Ready); 194 AllRegionsReady = m_localScenes.FindAll(s => !s.Ready).Count == 0;
211 } 195 }
212 196
213 public void SendSimOnlineNotification(ulong regionHandle) 197 public void SendSimOnlineNotification(ulong regionHandle)
214 { 198 {
215 RegionInfo Result = null; 199 RegionInfo Result = null;
216 200
217 lock (m_localScenes) 201 Scene s = m_localScenes.FindValue(delegate(Scene x)
218 {
219 for (int i = 0; i < m_localScenes.Count; i++)
220 {
221 if (m_localScenes[i].RegionInfo.RegionHandle == regionHandle)
222 { 202 {
223 // Inform other regions to tell their avatar about me 203 if (x.RegionInfo.RegionHandle == regionHandle)
224 Result = m_localScenes[i].RegionInfo; 204 return true;
225 } 205 return false;
226 } 206 });
207
208 if (s != null)
209 {
210 List<Scene> sceneList = Scenes;
227 211
228 if (Result != null) 212 for (int i = 0; i < sceneList.Count; i++)
229 { 213 {
230 for (int i = 0; i < m_localScenes.Count; i++) 214 if (sceneList[i]!= s)
231 { 215 {
232 if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle) 216 // Inform other regions to tell their avatar about me
233 { 217 //sceneList[i].OtherRegionUp(Result);
234 // Inform other regions to tell their avatar about me
235 //m_localScenes[i].OtherRegionUp(Result);
236 }
237 } 218 }
238 } 219 }
239 else 220 }
240 { 221 else
241 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up"); 222 {
242 } 223 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up");
243 } 224 }
244 } 225 }
245 226
@@ -368,16 +349,12 @@ namespace OpenSim.Region.Framework.Scenes
368 } 349 }
369 else 350 else
370 { 351 {
371 lock (m_localScenes) 352 Scene s;
353
354 if (m_localScenes.TryGetValue(regionName, out s))
372 { 355 {
373 foreach (Scene scene in m_localScenes) 356 CurrentScene = s;
374 { 357 return true;
375 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
376 {
377 CurrentScene = scene;
378 return true;
379 }
380 }
381 } 358 }
382 359
383 return false; 360 return false;
@@ -386,18 +363,14 @@ namespace OpenSim.Region.Framework.Scenes
386 363
387 public bool TrySetCurrentScene(UUID regionID) 364 public bool TrySetCurrentScene(UUID regionID)
388 { 365 {
389 m_log.Debug("Searching for Region: '" + regionID + "'"); 366// m_log.Debug("Searching for Region: '" + regionID + "'");
390 367
391 lock (m_localScenes) 368 Scene s;
369
370 if (m_localScenes.TryGetValue(regionID, out s))
392 { 371 {
393 foreach (Scene scene in m_localScenes) 372 CurrentScene = s;
394 { 373 return true;
395 if (scene.RegionInfo.RegionID == regionID)
396 {
397 CurrentScene = scene;
398 return true;
399 }
400 }
401 } 374 }
402 375
403 return false; 376 return false;
@@ -405,52 +378,24 @@ namespace OpenSim.Region.Framework.Scenes
405 378
406 public bool TryGetScene(string regionName, out Scene scene) 379 public bool TryGetScene(string regionName, out Scene scene)
407 { 380 {
408 lock (m_localScenes) 381 return m_localScenes.TryGetValue(regionName, out scene);
409 {
410 foreach (Scene mscene in m_localScenes)
411 {
412 if (String.Compare(mscene.RegionInfo.RegionName, regionName, true) == 0)
413 {
414 scene = mscene;
415 return true;
416 }
417 }
418 }
419
420 scene = null;
421 return false;
422 } 382 }
423 383
424 public bool TryGetScene(UUID regionID, out Scene scene) 384 public bool TryGetScene(UUID regionID, out Scene scene)
425 { 385 {
426 lock (m_localScenes) 386 return m_localScenes.TryGetValue(regionID, out scene);
427 {
428 foreach (Scene mscene in m_localScenes)
429 {
430 if (mscene.RegionInfo.RegionID == regionID)
431 {
432 scene = mscene;
433 return true;
434 }
435 }
436 }
437
438 scene = null;
439 return false;
440 } 387 }
441 388
442 public bool TryGetScene(uint locX, uint locY, out Scene scene) 389 public bool TryGetScene(uint locX, uint locY, out Scene scene)
443 { 390 {
444 lock (m_localScenes) 391 List<Scene> sceneList = Scenes;
392 foreach (Scene mscene in sceneList)
445 { 393 {
446 foreach (Scene mscene in m_localScenes) 394 if (mscene.RegionInfo.RegionLocX == locX &&
395 mscene.RegionInfo.RegionLocY == locY)
447 { 396 {
448 if (mscene.RegionInfo.RegionLocX == locX && 397 scene = mscene;
449 mscene.RegionInfo.RegionLocY == locY) 398 return true;
450 {
451 scene = mscene;
452 return true;
453 }
454 } 399 }
455 } 400 }
456 401
@@ -460,16 +405,14 @@ namespace OpenSim.Region.Framework.Scenes
460 405
461 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene) 406 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene)
462 { 407 {
463 lock (m_localScenes) 408 List<Scene> sceneList = Scenes;
409 foreach (Scene mscene in sceneList)
464 { 410 {
465 foreach (Scene mscene in m_localScenes) 411 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) &&
412 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port))
466 { 413 {
467 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) && 414 scene = mscene;
468 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port)) 415 return true;
469 {
470 scene = mscene;
471 return true;
472 }
473 } 416 }
474 } 417 }
475 418
@@ -511,15 +454,10 @@ namespace OpenSim.Region.Framework.Scenes
511 454
512 public RegionInfo GetRegionInfo(UUID regionID) 455 public RegionInfo GetRegionInfo(UUID regionID)
513 { 456 {
514 lock (m_localScenes) 457 Scene s;
458 if (m_localScenes.TryGetValue(regionID, out s))
515 { 459 {
516 foreach (Scene scene in m_localScenes) 460 return s.RegionInfo;
517 {
518 if (scene.RegionInfo.RegionID == regionID)
519 {
520 return scene.RegionInfo;
521 }
522 }
523 } 461 }
524 462
525 return null; 463 return null;
@@ -537,14 +475,12 @@ namespace OpenSim.Region.Framework.Scenes
537 475
538 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar) 476 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar)
539 { 477 {
540 lock (m_localScenes) 478 List<Scene> sceneList = Scenes;
479 foreach (Scene scene in sceneList)
541 { 480 {
542 foreach (Scene scene in m_localScenes) 481 if (scene.TryGetScenePresence(avatarId, out avatar))
543 { 482 {
544 if (scene.TryGetScenePresence(avatarId, out avatar)) 483 return true;
545 {
546 return true;
547 }
548 } 484 }
549 } 485 }
550 486
@@ -554,15 +490,13 @@ namespace OpenSim.Region.Framework.Scenes
554 490
555 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar) 491 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar)
556 { 492 {
557 lock (m_localScenes) 493 List<Scene> sceneList = Scenes;
494 foreach (Scene scene in sceneList)
558 { 495 {
559 foreach (Scene scene in m_localScenes) 496 avatar = scene.GetScenePresence(avatarId);
560 {
561 avatar = scene.GetScenePresence(avatarId);
562 497
563 if (avatar != null && !avatar.IsChildAgent) 498 if (avatar != null && !avatar.IsChildAgent)
564 return true; 499 return true;
565 }
566 } 500 }
567 501
568 avatar = null; 502 avatar = null;
@@ -572,21 +506,19 @@ namespace OpenSim.Region.Framework.Scenes
572 public void CloseScene(Scene scene) 506 public void CloseScene(Scene scene)
573 { 507 {
574 lock (m_localScenes) 508 lock (m_localScenes)
575 m_localScenes.Remove(scene); 509 m_localScenes.Remove(scene.RegionInfo.RegionID);
576 510
577 scene.Close(); 511 scene.Close();
578 } 512 }
579 513
580 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) 514 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
581 { 515 {
582 lock (m_localScenes) 516 List<Scene> sceneList = Scenes;
517 foreach (Scene scene in sceneList)
583 { 518 {
584 foreach (Scene scene in m_localScenes) 519 if (scene.TryGetAvatarByName(avatarName, out avatar))
585 { 520 {
586 if (scene.TryGetAvatarByName(avatarName, out avatar)) 521 return true;
587 {
588 return true;
589 }
590 } 522 }
591 } 523 }
592 524
@@ -596,14 +528,12 @@ namespace OpenSim.Region.Framework.Scenes
596 528
597 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp) 529 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp)
598 { 530 {
599 lock (m_localScenes) 531 List<Scene> sceneList = Scenes;
532 foreach (Scene scene in sceneList)
600 { 533 {
601 foreach (Scene scene in m_localScenes) 534 sp = scene.GetScenePresence(firstName, lastName);
602 { 535 if (sp != null && !sp.IsChildAgent)
603 sp = scene.GetScenePresence(firstName, lastName); 536 return true;
604 if (sp != null && !sp.IsChildAgent)
605 return true;
606 }
607 } 537 }
608 538
609 sp = null; 539 sp = null;
@@ -612,8 +542,8 @@ namespace OpenSim.Region.Framework.Scenes
612 542
613 public void ForEachScene(Action<Scene> action) 543 public void ForEachScene(Action<Scene> action)
614 { 544 {
615 lock (m_localScenes) 545 List<Scene> sceneList = Scenes;
616 m_localScenes.ForEach(action); 546 sceneList.ForEach(action);
617 } 547 }
618 } 548 }
619} 549}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 81cef5b..98617d1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -88,10 +88,6 @@ namespace OpenSim.Region.Framework.Scenes
88 /// <summary> 88 /// <summary>
89 /// Stop and remove the scripts contained in all the prims in this group 89 /// Stop and remove the scripts contained in all the prims in this group
90 /// </summary> 90 /// </summary>
91 /// <param name="sceneObjectBeingDeleted">
92 /// Should be true if these scripts are being removed because the scene
93 /// object is being deleted. This will prevent spurious updates to the client.
94 /// </param>
95 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 91 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
96 { 92 {
97 SceneObjectPart[] parts = m_parts.GetArray(); 93 SceneObjectPart[] parts = m_parts.GetArray();
@@ -254,6 +250,11 @@ namespace OpenSim.Region.Framework.Scenes
254 250
255 public uint GetEffectivePermissions() 251 public uint GetEffectivePermissions()
256 { 252 {
253 return GetEffectivePermissions(false);
254 }
255
256 public uint GetEffectivePermissions(bool useBase)
257 {
257 uint perms=(uint)(PermissionMask.Modify | 258 uint perms=(uint)(PermissionMask.Modify |
258 PermissionMask.Copy | 259 PermissionMask.Copy |
259 PermissionMask.Move | 260 PermissionMask.Move |
@@ -265,8 +266,12 @@ namespace OpenSim.Region.Framework.Scenes
265 for (int i = 0; i < parts.Length; i++) 266 for (int i = 0; i < parts.Length; i++)
266 { 267 {
267 SceneObjectPart part = parts[i]; 268 SceneObjectPart part = parts[i];
268// m_log.DebugFormat("[SCENE OBJECT GROUP INVENTORY]: Effective perms of {0} are {1}", part.Name, (OpenMetaverse.PermissionMask)part.OwnerMask); 269
269 ownerMask &= part.OwnerMask; 270 if (useBase)
271 ownerMask &= part.BaseMask;
272 else
273 ownerMask &= part.OwnerMask;
274
270 perms &= part.Inventory.MaskEffectivePermissions(); 275 perms &= part.Inventory.MaskEffectivePermissions();
271 } 276 }
272 277
@@ -408,6 +413,9 @@ namespace OpenSim.Region.Framework.Scenes
408 413
409 public void ResumeScripts() 414 public void ResumeScripts()
410 { 415 {
416 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
417 return;
418
411 SceneObjectPart[] parts = m_parts.GetArray(); 419 SceneObjectPart[] parts = m_parts.GetArray();
412 for (int i = 0; i < parts.Length; i++) 420 for (int i = 0; i < parts.Length; i++)
413 parts[i].Inventory.ResumeScripts(); 421 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index d08237e..e780f86 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,12 +24,13 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.ComponentModel; 29using System.ComponentModel;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Drawing; 31using System.Drawing;
32using System.IO; 32using System.IO;
33using System.Diagnostics;
33using System.Linq; 34using System.Linq;
34using System.Threading; 35using System.Threading;
35using System.Xml; 36using System.Xml;
@@ -45,6 +46,7 @@ using OpenSim.Services.Interfaces;
45 46
46namespace OpenSim.Region.Framework.Scenes 47namespace OpenSim.Region.Framework.Scenes
47{ 48{
49
48 [Flags] 50 [Flags]
49 public enum scriptEvents 51 public enum scriptEvents
50 { 52 {
@@ -80,14 +82,14 @@ namespace OpenSim.Region.Framework.Scenes
80 object_rez = 4194304 82 object_rez = 4194304
81 } 83 }
82 84
83 struct scriptPosTarget 85 public struct scriptPosTarget
84 { 86 {
85 public Vector3 targetPos; 87 public Vector3 targetPos;
86 public float tolerance; 88 public float tolerance;
87 public uint handle; 89 public uint handle;
88 } 90 }
89 91
90 struct scriptRotTarget 92 public struct scriptRotTarget
91 { 93 {
92 public Quaternion targetRot; 94 public Quaternion targetRot;
93 public float tolerance; 95 public float tolerance;
@@ -109,6 +111,9 @@ namespace OpenSim.Region.Framework.Scenes
109 STATUS_ROTATE_X = 0x002, 111 STATUS_ROTATE_X = 0x002,
110 STATUS_ROTATE_Y = 0x004, 112 STATUS_ROTATE_Y = 0x004,
111 STATUS_ROTATE_Z = 0x008, 113 STATUS_ROTATE_Z = 0x008,
114 NOT_STATUS_ROTATE_X = 0xFD,
115 NOT_STATUS_ROTATE_Y = 0xFB,
116 NOT_STATUS_ROTATE_Z = 0xF7
112 } 117 }
113 118
114 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm 119 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm
@@ -121,8 +126,11 @@ namespace OpenSim.Region.Framework.Scenes
121 /// since the group's last persistent backup 126 /// since the group's last persistent backup
122 /// </summary> 127 /// </summary>
123 private bool m_hasGroupChanged = false; 128 private bool m_hasGroupChanged = false;
124 private long timeFirstChanged; 129 private long timeFirstChanged = 0;
125 private long timeLastChanged; 130 private long timeLastChanged = 0;
131 private long m_maxPersistTime = 0;
132 private long m_minPersistTime = 0;
133// private Random m_rand;
126 134
127 /// <summary> 135 /// <summary>
128 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage 136 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
@@ -139,9 +147,44 @@ namespace OpenSim.Region.Framework.Scenes
139 { 147 {
140 if (value) 148 if (value)
141 { 149 {
150
151 if (m_isBackedUp)
152 {
153 m_scene.SceneGraph.FireChangeBackup(this);
154 }
142 timeLastChanged = DateTime.Now.Ticks; 155 timeLastChanged = DateTime.Now.Ticks;
143 if (!m_hasGroupChanged) 156 if (!m_hasGroupChanged)
144 timeFirstChanged = DateTime.Now.Ticks; 157 timeFirstChanged = DateTime.Now.Ticks;
158 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
159 {
160/*
161 if (m_rand == null)
162 {
163 byte[] val = new byte[16];
164 m_rootPart.UUID.ToBytes(val, 0);
165 m_rand = new Random(BitConverter.ToInt32(val, 0));
166 }
167 */
168 if (m_scene.GetRootAgentCount() == 0)
169 {
170 //If the region is empty, this change has been made by an automated process
171 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
172
173// float factor = 1.5f + (float)(m_rand.NextDouble());
174 float factor = 2.0f;
175 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
176 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
177 }
178 else
179 {
180 //If the region is not empty, we want to obey the minimum and maximum persist times
181 //but add a random factor so we stagger the object persistance a little
182// m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
183// m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
184 m_maxPersistTime = m_scene.m_persistAfter;
185 m_minPersistTime = m_scene.m_dontPersistBefore;
186 }
187 }
145 } 188 }
146 m_hasGroupChanged = value; 189 m_hasGroupChanged = value;
147 190
@@ -172,6 +215,7 @@ namespace OpenSim.Region.Framework.Scenes
172 get { return m_groupContainsForeignPrims; } 215 get { return m_groupContainsForeignPrims; }
173 } 216 }
174 217
218 public bool HasGroupChangedDueToDelink { get; set; }
175 219
176 private bool isTimeToPersist() 220 private bool isTimeToPersist()
177 { 221 {
@@ -181,8 +225,19 @@ namespace OpenSim.Region.Framework.Scenes
181 return false; 225 return false;
182 if (m_scene.ShuttingDown) 226 if (m_scene.ShuttingDown)
183 return true; 227 return true;
228
229 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
230 {
231 m_maxPersistTime = m_scene.m_persistAfter;
232 m_minPersistTime = m_scene.m_dontPersistBefore;
233 }
234
184 long currentTime = DateTime.Now.Ticks; 235 long currentTime = DateTime.Now.Ticks;
185 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 236
237 if (timeLastChanged == 0) timeLastChanged = currentTime;
238 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
239
240 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
186 return true; 241 return true;
187 return false; 242 return false;
188 } 243 }
@@ -240,6 +295,11 @@ namespace OpenSim.Region.Framework.Scenes
240 { 295 {
241 AttachmentPoint = 0; 296 AttachmentPoint = 0;
242 297
298 // Don't zap trees
299 if (RootPart.Shape.PCode == (byte)PCode.Tree ||
300 RootPart.Shape.PCode == (byte)PCode.NewTree)
301 return;
302
243 // Even though we don't use child part state parameters for attachments any more, we still need to set 303 // Even though we don't use child part state parameters for attachments any more, we still need to set
244 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if 304 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if
245 // we store them correctly, scene objects that we receive from elsewhere might not. 305 // we store them correctly, scene objects that we receive from elsewhere might not.
@@ -293,21 +353,38 @@ namespace OpenSim.Region.Framework.Scenes
293 /// </summary> 353 /// </summary>
294 public bool Backup { get; private set; } 354 public bool Backup { get; private set; }
295 355
356 private bool m_isBackedUp;
357
358 public bool IsBackedUp
359 {
360 get { return m_isBackedUp; }
361 }
362
296 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>(); 363 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>();
297 364
298 protected ulong m_regionHandle; 365 protected ulong m_regionHandle;
299 protected SceneObjectPart m_rootPart; 366 protected SceneObjectPart m_rootPart;
300 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); 367 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
301 368
302 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); 369 private SortedDictionary<uint, scriptPosTarget> m_targets = new SortedDictionary<uint, scriptPosTarget>();
303 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); 370 private SortedDictionary<uint, scriptRotTarget> m_rotTargets = new SortedDictionary<uint, scriptRotTarget>();
371
372 public SortedDictionary<uint, scriptPosTarget> AtTargets
373 {
374 get { return m_targets; }
375 }
376
377 public SortedDictionary<uint, scriptRotTarget> RotTargets
378 {
379 get { return m_rotTargets; }
380 }
304 381
305 private bool m_scriptListens_atTarget; 382 private bool m_scriptListens_atTarget;
306 private bool m_scriptListens_notAtTarget; 383 private bool m_scriptListens_notAtTarget;
307
308 private bool m_scriptListens_atRotTarget; 384 private bool m_scriptListens_atRotTarget;
309 private bool m_scriptListens_notAtRotTarget; 385 private bool m_scriptListens_notAtRotTarget;
310 386
387 public bool m_dupeInProgress = false;
311 internal Dictionary<UUID, string> m_savedScriptState; 388 internal Dictionary<UUID, string> m_savedScriptState;
312 389
313 #region Properties 390 #region Properties
@@ -344,6 +421,16 @@ namespace OpenSim.Region.Framework.Scenes
344 get { return m_parts.Count; } 421 get { return m_parts.Count; }
345 } 422 }
346 423
424// protected Quaternion m_rotation = Quaternion.Identity;
425//
426// public virtual Quaternion Rotation
427// {
428// get { return m_rotation; }
429// set {
430// m_rotation = value;
431// }
432// }
433
347 public Quaternion GroupRotation 434 public Quaternion GroupRotation
348 { 435 {
349 get { return m_rootPart.RotationOffset; } 436 get { return m_rootPart.RotationOffset; }
@@ -458,6 +545,10 @@ namespace OpenSim.Region.Framework.Scenes
458 public uint ParentID; 545 public uint ParentID;
459 } 546 }
460 547
548
549 public bool inTransit = false;
550 public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos);
551
461 /// <summary> 552 /// <summary>
462 /// The absolute position of this scene object in the scene 553 /// The absolute position of this scene object in the scene
463 /// </summary> 554 /// </summary>
@@ -467,183 +558,269 @@ namespace OpenSim.Region.Framework.Scenes
467 set 558 set
468 { 559 {
469 Vector3 val = value; 560 Vector3 val = value;
561 if (Scene != null
562 && !Scene.PositionIsInCurrentRegion(val)
563 && !IsAttachmentCheckFull()
564 && !Scene.LoadingPrims
565 )
566 {
567 if (!inTransit)
568 {
569 inTransit = true;
570 SOGCrossDelegate d = CrossAsync;
571 d.BeginInvoke(this, val, CrossAsyncCompleted, d);
572 }
573 return;
574 }
470 575
471 if (Scene != null) 576 if (RootPart.GetStatusSandbox())
472 { 577 {
473 if ( 578 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
474 !Scene.PositionIsInCurrentRegion(val)
475 && !IsAttachmentCheckFull()
476 && (!Scene.LoadingPrims)
477 )
478 { 579 {
479 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 580 RootPart.ScriptSetPhysicsStatus(false);
480 EntityTransferContext ctx = new EntityTransferContext();
481 Vector3 newpos = Vector3.Zero;
482 string failureReason = String.Empty;
483 OpenSim.Services.Interfaces.GridRegion destination = null;
484 581
485 if (m_rootPart.KeyframeMotion != null) 582 if (Scene != null)
486 m_rootPart.KeyframeMotion.StartCrossingCheck(); 583 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
584 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
487 585
488 bool canCross = true; 586 return;
489 foreach (ScenePresence av in GetSittingAvatars()) 587 }
490 { 588 }
491 // We need to cross these agents. First, let's find
492 // out if any of them can't cross for some reason.
493 // We have to deny the crossing entirely if any
494 // of them are banned. Alternatively, we could
495 // unsit banned agents....
496 589
590 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
591 if (m_dupeInProgress || IsDeleted)
592 triggerScriptEvent = false;
497 593
498 // We set the avatar position as being the object 594 m_rootPart.GroupPosition = val;
499 // position to get the region to send to
500 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, ctx, out newpos, out failureReason)) == null)
501 {
502 canCross = false;
503 break;
504 }
505 595
506 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); 596 // Restuff the new GroupPosition into each child SOP of the linkset.
507 } 597 // this is needed because physics may not have linksets but just loose SOPs in world
508 598
509 if (canCross) 599 SceneObjectPart[] parts = m_parts.GetArray();
510 {
511 // We unparent the SP quietly so that it won't
512 // be made to stand up
513 600
514 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); 601 foreach (SceneObjectPart part in parts)
602 {
603 if (part != m_rootPart)
604 part.GroupPosition = val;
605 }
515 606
516 foreach (ScenePresence av in GetSittingAvatars()) 607 foreach (ScenePresence av in m_sittingAvatars)
517 { 608 {
518 avtocrossInfo avinfo = new avtocrossInfo(); 609 av.sitSOGmoved();
519 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID); 610 }
520 if (parentPart != null)
521 av.ParentUUID = parentPart.UUID;
522 611
523 avinfo.av = av;
524 avinfo.ParentID = av.ParentID;
525 avsToCross.Add(avinfo);
526 612
527 av.PrevSitOffset = av.OffsetPosition; 613 // now that position is changed tell it to scripts
528 av.ParentID = 0; 614 if (triggerScriptEvent)
529 } 615 {
616 foreach (SceneObjectPart part in parts)
617 {
618 part.TriggerScriptChangedEvent(Changed.POSITION);
619 }
620 }
530 621
531 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 622 if (Scene != null)
623 Scene.EventManager.TriggerParcelPrimCountTainted();
532 624
533 // Normalize 625 }
534 if (val.X >= m_scene.RegionInfo.RegionSizeX) 626 }
535 val.X -= m_scene.RegionInfo.RegionSizeX;
536 if (val.Y >= m_scene.RegionInfo.RegionSizeY)
537 val.Y -= m_scene.RegionInfo.RegionSizeY;
538 if (val.X < 0)
539 val.X += m_scene.RegionInfo.RegionSizeX;
540 if (val.Y < 0)
541 val.Y += m_scene.RegionInfo.RegionSizeY;
542 627
543 // If it's deleted, crossing was successful 628 public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val)
544 if (IsDeleted) 629 {
545 { 630 Scene sogScene = sog.m_scene;
546 foreach (avtocrossInfo avinfo in avsToCross) 631 IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
547 {
548 ScenePresence av = avinfo.av;
549 if (!av.IsInTransit) // just in case...
550 {
551 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
552
553 av.IsInTransit = true;
554
555 // A temporary measure to allow regression tests to work.
556 // Quite possibly, all BeginInvoke() calls should be replaced by Util.FireAndForget
557 // or similar since BeginInvoke() always uses the system threadpool to launch
558 // threads rather than any replace threadpool that we might be using.
559 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
560 {
561 entityTransfer.CrossAgentToNewRegionAsync(av, val, destination, av.Flying, ctx);
562 CrossAgentToNewRegionCompleted(av);
563 }
564 else
565 {
566 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
567 d.BeginInvoke(
568 av, val, destination, av.Flying, ctx,
569 ar => CrossAgentToNewRegionCompleted(d.EndInvoke(ar)), null);
570 }
571 }
572 else
573 {
574 m_log.DebugFormat("[SCENE OBJECT]: Not crossing avatar {0} to {1} because it's already in transit", av.Name, val);
575 }
576 }
577 632
578 return; 633 Vector3 newpos = Vector3.Zero;
579 } 634 OpenSim.Services.Interfaces.GridRegion destination = null;
580 else // cross failed, put avas back ?? 635
636 if (sog.RootPart.DIE_AT_EDGE)
637 {
638 try
639 {
640 sogScene.DeleteSceneObject(sog, false);
641 }
642 catch (Exception)
643 {
644 m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
645 }
646 return sog;
647 }
648
649 if (sog.RootPart.RETURN_AT_EDGE)
650 {
651 // We remove the object here
652 try
653 {
654 List<uint> localIDs = new List<uint>();
655 localIDs.Add(sog.RootPart.LocalId);
656 sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition,
657 "Returned at region cross");
658 sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero);
659 }
660 catch (Exception)
661 {
662 m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
663 }
664 return sog;
665 }
666
667 if (sog.m_rootPart.KeyframeMotion != null)
668 sog.m_rootPart.KeyframeMotion.StartCrossingCheck();
669
670 if (entityTransfer == null)
671 return sog;
672
673 destination = entityTransfer.GetObjectDestination(sog, val, out newpos);
674 if (destination == null)
675 return sog;
676
677 if (sog.m_sittingAvatars.Count == 0)
678 {
679 entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true, true);
680 return sog;
681 }
682
683 string reason = String.Empty;
684 EntityTransferContext ctx = new EntityTransferContext();
685
686 foreach (ScenePresence av in sog.m_sittingAvatars)
687 {
688 // We need to cross these agents. First, let's find
689 // out if any of them can't cross for some reason.
690 // We have to deny the crossing entirely if any
691 // of them are banned. Alternatively, we could
692 // unsit banned agents....
693
694 // We set the avatar position as being the object
695 // position to get the region to send to
696 if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, ctx, out reason))
697 {
698 return sog;
699 }
700 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
701 }
702
703 // We unparent the SP quietly so that it won't
704 // be made to stand up
705
706 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
707
708 foreach (ScenePresence av in sog.m_sittingAvatars)
709 {
710 avtocrossInfo avinfo = new avtocrossInfo();
711 SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID);
712 if (parentPart != null)
713 av.ParentUUID = parentPart.UUID;
714
715 avinfo.av = av;
716 avinfo.ParentID = av.ParentID;
717 avsToCross.Add(avinfo);
718
719 av.PrevSitOffset = av.OffsetPosition;
720 av.ParentID = 0;
721 }
722
723 if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true, false))
724 {
725 foreach (avtocrossInfo avinfo in avsToCross)
726 {
727 ScenePresence av = avinfo.av;
728 if (!av.IsInTransit) // just in case...
729 {
730 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
731
732 av.IsInTransit = true;
733
734// CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
735// d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
736 entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, ctx);
737 if (av.IsChildAgent)
738 {
739 // avatar crossed do some extra cleanup
740 if (av.ParentUUID != UUID.Zero)
581 { 741 {
582 foreach (avtocrossInfo avinfo in avsToCross) 742 av.ClearControls();
583 { 743 av.ParentPart = null;
584 ScenePresence av = avinfo.av;
585 av.ParentUUID = UUID.Zero;
586 av.ParentID = avinfo.ParentID;
587 }
588 } 744 }
589 } 745 }
590 else 746 else
591 { 747 {
592 if (m_rootPart.KeyframeMotion != null) 748 // avatar cross failed we need do dedicated standUp
593 m_rootPart.KeyframeMotion.CrossingFailure(); 749 // part of it was done at CrossAgentToNewRegionAsync
594 750 // so for now just remove the sog controls
595 if (RootPart.PhysActor != null) 751 // this may need extra care
596 { 752 av.UnRegisterSeatControls(sog.UUID);
597 RootPart.PhysActor.CrossingFailure();
598 }
599 } 753 }
600 754
601 Vector3 oldp = AbsolutePosition; 755 av.ParentUUID = UUID.Zero;
602 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f); 756 // In any case
603 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f); 757 av.IsInTransit = false;
604 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight); 758
759 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname);
605 } 760 }
761 else
762 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val);
606 } 763 }
607 764 avsToCross.Clear();
608 if (RootPart.GetStatusSandbox()) 765 sog.RemoveScriptInstances(true);
766 return sog;
767 }
768 else // cross failed, put avas back ??
769 {
770 foreach (avtocrossInfo avinfo in avsToCross)
609 { 771 {
610 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 772 ScenePresence av = avinfo.av;
611 { 773 av.ParentUUID = UUID.Zero;
612 RootPart.ScriptSetPhysicsStatus(false); 774 av.ParentID = avinfo.ParentID;
613
614 if (Scene != null)
615 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
616 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
617
618 return;
619 }
620 } 775 }
621
622 // Restuff the new GroupPosition into each SOP of the linkset.
623 // This has the affect of resetting and tainting the physics actors.
624 SceneObjectPart[] parts = m_parts.GetArray();
625 for (int i = 0; i < parts.Length; i++)
626 parts[i].GroupPosition = val;
627
628 //if (m_rootPart.PhysActor != null)
629 //{
630 //m_rootPart.PhysActor.Position =
631 //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
632 //m_rootPart.GroupPosition.Z);
633 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
634 //}
635
636 if (Scene != null)
637 Scene.EventManager.TriggerParcelPrimCountTainted();
638 } 776 }
777 avsToCross.Clear();
778
779 return sog;
639 } 780 }
640 781
641 public override Vector3 Velocity 782 public void CrossAsyncCompleted(IAsyncResult iar)
642 { 783 {
643 get { return RootPart.Velocity; } 784 SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState;
644 set { RootPart.Velocity = value; } 785 SceneObjectGroup sog = icon.EndInvoke(iar);
786
787 if (!sog.IsDeleted)
788 {
789 SceneObjectPart rootp = sog.m_rootPart;
790 Vector3 oldp = rootp.GroupPosition;
791 oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
792 oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
793 rootp.GroupPosition = oldp;
794
795 SceneObjectPart[] parts = sog.m_parts.GetArray();
796
797 foreach (SceneObjectPart part in parts)
798 {
799 if (part != rootp)
800 part.GroupPosition = oldp;
801 }
802
803 foreach (ScenePresence av in sog.m_sittingAvatars)
804 {
805 av.sitSOGmoved();
806 }
807
808 sog.Velocity = Vector3.Zero;
809
810 if (sog.m_rootPart.KeyframeMotion != null)
811 sog.m_rootPart.KeyframeMotion.CrossingFailure();
812
813 if (sog.RootPart.PhysActor != null)
814 {
815 sog.RootPart.PhysActor.CrossingFailure();
816 }
817
818 sog.inTransit = false;
819 sog.ScheduleGroupForFullUpdate();
820 }
645 } 821 }
646 822
823/* outdated
647 private void CrossAgentToNewRegionCompleted(ScenePresence agent) 824 private void CrossAgentToNewRegionCompleted(ScenePresence agent)
648 { 825 {
649 //// If the cross was successful, this agent is a child agent 826 //// If the cross was successful, this agent is a child agent
@@ -651,6 +828,7 @@ namespace OpenSim.Region.Framework.Scenes
651 { 828 {
652 if (agent.ParentUUID != UUID.Zero) 829 if (agent.ParentUUID != UUID.Zero)
653 { 830 {
831 agent.HandleForceReleaseControls(agent.ControllingClient,agent.UUID);
654 agent.ParentPart = null; 832 agent.ParentPart = null;
655// agent.ParentPosition = Vector3.Zero; 833// agent.ParentPosition = Vector3.Zero;
656// agent.ParentUUID = UUID.Zero; 834// agent.ParentUUID = UUID.Zero;
@@ -667,6 +845,12 @@ namespace OpenSim.Region.Framework.Scenes
667 845
668 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 846 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
669 } 847 }
848*/
849 public override Vector3 Velocity
850 {
851 get { return RootPart.Velocity; }
852 set { RootPart.Velocity = value; }
853 }
670 854
671 public override uint LocalId 855 public override uint LocalId
672 { 856 {
@@ -742,6 +926,11 @@ namespace OpenSim.Region.Framework.Scenes
742 m_isSelected = value; 926 m_isSelected = value;
743 // Tell physics engine that group is selected 927 // Tell physics engine that group is selected
744 928
929 // this is not right
930 // but ode engines should only really need to know about root part
931 // so they can put entire object simulation on hold and not colliding
932 // keep as was for now
933
745 PhysicsActor pa = m_rootPart.PhysActor; 934 PhysicsActor pa = m_rootPart.PhysActor;
746 if (pa != null) 935 if (pa != null)
747 { 936 {
@@ -763,13 +952,47 @@ namespace OpenSim.Region.Framework.Scenes
763 } 952 }
764 } 953 }
765 954
955 public void PartSelectChanged(bool partSelect)
956 {
957 // any part selected makes group selected
958 if (m_isSelected == partSelect)
959 return;
960
961 if (partSelect)
962 {
963 IsSelected = partSelect;
964// if (!IsAttachment)
965// ScheduleGroupForFullUpdate();
966 }
967 else
968 {
969 // bad bad bad 2 heavy for large linksets
970 // since viewer does send lot of (un)selects
971 // this needs to be replaced by a specific list or count ?
972 // but that will require extra code in several places
973
974 SceneObjectPart[] parts = m_parts.GetArray();
975 for (int i = 0; i < parts.Length; i++)
976 {
977 SceneObjectPart part = parts[i];
978 if (part.IsSelected)
979 return;
980 }
981 IsSelected = partSelect;
982// if (!IsAttachment)
983// {
984// ScheduleGroupForFullUpdate();
985// }
986 }
987 }
988 // PlaySoundMasterPrim no longer in use to remove
766 private SceneObjectPart m_PlaySoundMasterPrim = null; 989 private SceneObjectPart m_PlaySoundMasterPrim = null;
767 public SceneObjectPart PlaySoundMasterPrim 990 public SceneObjectPart PlaySoundMasterPrim
768 { 991 {
769 get { return m_PlaySoundMasterPrim; } 992 get { return m_PlaySoundMasterPrim; }
770 set { m_PlaySoundMasterPrim = value; } 993 set { m_PlaySoundMasterPrim = value; }
771 } 994 }
772 995 // PlaySoundSlavePrims no longer in use to remove
773 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); 996 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
774 public List<SceneObjectPart> PlaySoundSlavePrims 997 public List<SceneObjectPart> PlaySoundSlavePrims
775 { 998 {
@@ -777,6 +1000,7 @@ namespace OpenSim.Region.Framework.Scenes
777 set { m_PlaySoundSlavePrims = value; } 1000 set { m_PlaySoundSlavePrims = value; }
778 } 1001 }
779 1002
1003 // LoopSoundMasterPrim no longer in use to remove
780 private SceneObjectPart m_LoopSoundMasterPrim = null; 1004 private SceneObjectPart m_LoopSoundMasterPrim = null;
781 public SceneObjectPart LoopSoundMasterPrim 1005 public SceneObjectPart LoopSoundMasterPrim
782 { 1006 {
@@ -784,6 +1008,7 @@ namespace OpenSim.Region.Framework.Scenes
784 set { m_LoopSoundMasterPrim = value; } 1008 set { m_LoopSoundMasterPrim = value; }
785 } 1009 }
786 1010
1011 // m_LoopSoundSlavePrims no longer in use to remove
787 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); 1012 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
788 public List<SceneObjectPart> LoopSoundSlavePrims 1013 public List<SceneObjectPart> LoopSoundSlavePrims
789 { 1014 {
@@ -863,6 +1088,7 @@ namespace OpenSim.Region.Framework.Scenes
863 /// </summary> 1088 /// </summary>
864 public SceneObjectGroup() 1089 public SceneObjectGroup()
865 { 1090 {
1091
866 } 1092 }
867 1093
868 /// <summary> 1094 /// <summary>
@@ -880,8 +1106,8 @@ namespace OpenSim.Region.Framework.Scenes
880 /// Constructor. This object is added to the scene later via AttachToScene() 1106 /// Constructor. This object is added to the scene later via AttachToScene()
881 /// </summary> 1107 /// </summary>
882 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 1108 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
883 :this(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)) 1109 {
884 { 1110 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
885 } 1111 }
886 1112
887 /// <summary> 1113 /// <summary>
@@ -956,7 +1182,10 @@ namespace OpenSim.Region.Framework.Scenes
956 /// </summary> 1182 /// </summary>
957 public virtual void AttachToBackup() 1183 public virtual void AttachToBackup()
958 { 1184 {
959 if (CanBeBackedUp) 1185 if (IsAttachment) return;
1186 m_scene.SceneGraph.FireAttachToBackup(this);
1187
1188// if (InSceneBackup)
960 { 1189 {
961// m_log.DebugFormat( 1190// m_log.DebugFormat(
962// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID); 1191// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID);
@@ -1003,6 +1232,13 @@ namespace OpenSim.Region.Framework.Scenes
1003 1232
1004 ApplyPhysics(); 1233 ApplyPhysics();
1005 1234
1235 if (RootPart.PhysActor != null)
1236 RootPart.Force = RootPart.Force;
1237 if (RootPart.PhysActor != null)
1238 RootPart.Torque = RootPart.Torque;
1239 if (RootPart.PhysActor != null)
1240 RootPart.Buoyancy = RootPart.Buoyancy;
1241
1006 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 1242 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
1007 // for the same object with very different properties. The caller must schedule the update. 1243 // for the same object with very different properties. The caller must schedule the update.
1008 //ScheduleGroupForFullUpdate(); 1244 //ScheduleGroupForFullUpdate();
@@ -1018,6 +1254,10 @@ namespace OpenSim.Region.Framework.Scenes
1018 EntityIntersection result = new EntityIntersection(); 1254 EntityIntersection result = new EntityIntersection();
1019 1255
1020 SceneObjectPart[] parts = m_parts.GetArray(); 1256 SceneObjectPart[] parts = m_parts.GetArray();
1257
1258 // Find closest hit here
1259 float idist = float.MaxValue;
1260
1021 for (int i = 0; i < parts.Length; i++) 1261 for (int i = 0; i < parts.Length; i++)
1022 { 1262 {
1023 SceneObjectPart part = parts[i]; 1263 SceneObjectPart part = parts[i];
@@ -1032,11 +1272,6 @@ namespace OpenSim.Region.Framework.Scenes
1032 1272
1033 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 1273 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
1034 1274
1035 // This may need to be updated to the maximum draw distance possible..
1036 // We might (and probably will) be checking for prim creation from other sims
1037 // when the camera crosses the border.
1038 float idist = Constants.RegionSize;
1039
1040 if (inter.HitTF) 1275 if (inter.HitTF)
1041 { 1276 {
1042 // We need to find the closest prim to return to the testcaller along the ray 1277 // We need to find the closest prim to return to the testcaller along the ray
@@ -1047,10 +1282,11 @@ namespace OpenSim.Region.Framework.Scenes
1047 result.obj = part; 1282 result.obj = part;
1048 result.normal = inter.normal; 1283 result.normal = inter.normal;
1049 result.distance = inter.distance; 1284 result.distance = inter.distance;
1285
1286 idist = inter.distance;
1050 } 1287 }
1051 } 1288 }
1052 } 1289 }
1053
1054 return result; 1290 return result;
1055 } 1291 }
1056 1292
@@ -1062,25 +1298,27 @@ namespace OpenSim.Region.Framework.Scenes
1062 /// <returns></returns> 1298 /// <returns></returns>
1063 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 1299 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
1064 { 1300 {
1065 maxX = -256f; 1301 maxX = float.MinValue;
1066 maxY = -256f; 1302 maxY = float.MinValue;
1067 maxZ = -256f; 1303 maxZ = float.MinValue;
1068 minX = 10000f; 1304 minX = float.MaxValue;
1069 minY = 10000f; 1305 minY = float.MaxValue;
1070 minZ = 10000f; 1306 minZ = float.MaxValue;
1071 1307
1072 SceneObjectPart[] parts = m_parts.GetArray(); 1308 SceneObjectPart[] parts = m_parts.GetArray();
1073 for (int i = 0; i < parts.Length; i++) 1309 foreach (SceneObjectPart part in parts)
1074 { 1310 {
1075 SceneObjectPart part = parts[i];
1076
1077 Vector3 worldPos = part.GetWorldPosition(); 1311 Vector3 worldPos = part.GetWorldPosition();
1078 Vector3 offset = worldPos - AbsolutePosition; 1312 Vector3 offset = worldPos - AbsolutePosition;
1079 Quaternion worldRot; 1313 Quaternion worldRot;
1080 if (part.ParentID == 0) 1314 if (part.ParentID == 0)
1315 {
1081 worldRot = part.RotationOffset; 1316 worldRot = part.RotationOffset;
1317 }
1082 else 1318 else
1319 {
1083 worldRot = part.GetWorldRotation(); 1320 worldRot = part.GetWorldRotation();
1321 }
1084 1322
1085 Vector3 frontTopLeft; 1323 Vector3 frontTopLeft;
1086 Vector3 frontTopRight; 1324 Vector3 frontTopRight;
@@ -1092,6 +1330,8 @@ namespace OpenSim.Region.Framework.Scenes
1092 Vector3 backBottomLeft; 1330 Vector3 backBottomLeft;
1093 Vector3 backBottomRight; 1331 Vector3 backBottomRight;
1094 1332
1333 // Vector3[] corners = new Vector3[8];
1334
1095 Vector3 orig = Vector3.Zero; 1335 Vector3 orig = Vector3.Zero;
1096 1336
1097 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1337 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -1126,6 +1366,38 @@ namespace OpenSim.Region.Framework.Scenes
1126 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1366 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
1127 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1367 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
1128 1368
1369
1370
1371 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1372 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1373 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1374 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1375 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1376 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1377 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1378 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1379
1380 //for (int i = 0; i < 8; i++)
1381 //{
1382 // corners[i] = corners[i] * worldRot;
1383 // corners[i] += offset;
1384
1385 // if (corners[i].X > maxX)
1386 // maxX = corners[i].X;
1387 // if (corners[i].X < minX)
1388 // minX = corners[i].X;
1389
1390 // if (corners[i].Y > maxY)
1391 // maxY = corners[i].Y;
1392 // if (corners[i].Y < minY)
1393 // minY = corners[i].Y;
1394
1395 // if (corners[i].Z > maxZ)
1396 // maxZ = corners[i].Y;
1397 // if (corners[i].Z < minZ)
1398 // minZ = corners[i].Z;
1399 //}
1400
1129 frontTopLeft = frontTopLeft * worldRot; 1401 frontTopLeft = frontTopLeft * worldRot;
1130 frontTopRight = frontTopRight * worldRot; 1402 frontTopRight = frontTopRight * worldRot;
1131 frontBottomLeft = frontBottomLeft * worldRot; 1403 frontBottomLeft = frontBottomLeft * worldRot;
@@ -1147,6 +1419,15 @@ namespace OpenSim.Region.Framework.Scenes
1147 backTopLeft += offset; 1419 backTopLeft += offset;
1148 backTopRight += offset; 1420 backTopRight += offset;
1149 1421
1422 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1423 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1424 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1425 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1426 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1427 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1428 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1429 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1430
1150 if (frontTopRight.X > maxX) 1431 if (frontTopRight.X > maxX)
1151 maxX = frontTopRight.X; 1432 maxX = frontTopRight.X;
1152 if (frontTopLeft.X > maxX) 1433 if (frontTopLeft.X > maxX)
@@ -1290,17 +1571,118 @@ namespace OpenSim.Region.Framework.Scenes
1290 1571
1291 #endregion 1572 #endregion
1292 1573
1574 public void GetResourcesCosts(SceneObjectPart apart,
1575 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1576 {
1577 // this information may need to be cached
1578
1579 float cost;
1580 float tmpcost;
1581
1582 bool ComplexCost = false;
1583
1584 SceneObjectPart p;
1585 SceneObjectPart[] parts;
1586
1587 lock (m_parts)
1588 {
1589 parts = m_parts.GetArray();
1590 }
1591
1592 int nparts = parts.Length;
1593
1594
1595 for (int i = 0; i < nparts; i++)
1596 {
1597 p = parts[i];
1598
1599 if (p.UsesComplexCost)
1600 {
1601 ComplexCost = true;
1602 break;
1603 }
1604 }
1605
1606 if (ComplexCost)
1607 {
1608 linksetResCost = 0;
1609 linksetPhysCost = 0;
1610 partCost = 0;
1611 partPhysCost = 0;
1612
1613 for (int i = 0; i < nparts; i++)
1614 {
1615 p = parts[i];
1616
1617 cost = p.StreamingCost;
1618 tmpcost = p.SimulationCost;
1619 if (tmpcost > cost)
1620 cost = tmpcost;
1621 tmpcost = p.PhysicsCost;
1622 if (tmpcost > cost)
1623 cost = tmpcost;
1624
1625 linksetPhysCost += tmpcost;
1626 linksetResCost += cost;
1627
1628 if (p == apart)
1629 {
1630 partCost = cost;
1631 partPhysCost = tmpcost;
1632 }
1633 }
1634 }
1635 else
1636 {
1637 partPhysCost = 1.0f;
1638 partCost = 1.0f;
1639 linksetResCost = (float)nparts;
1640 linksetPhysCost = linksetResCost;
1641 }
1642 }
1643
1644 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1645 {
1646 SceneObjectPart p;
1647 SceneObjectPart[] parts;
1648
1649 lock (m_parts)
1650 {
1651 parts = m_parts.GetArray();
1652 }
1653
1654 int nparts = parts.Length;
1655
1656 PhysCost = 0;
1657 StreamCost = 0;
1658 SimulCost = 0;
1659
1660 for (int i = 0; i < nparts; i++)
1661 {
1662 p = parts[i];
1663
1664 StreamCost += p.StreamingCost;
1665 SimulCost += p.SimulationCost;
1666 PhysCost += p.PhysicsCost;
1667 }
1668 }
1669
1293 public void SaveScriptedState(XmlTextWriter writer) 1670 public void SaveScriptedState(XmlTextWriter writer)
1294 { 1671 {
1672 SaveScriptedState(writer, false);
1673 }
1674
1675 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1676 {
1295 XmlDocument doc = new XmlDocument(); 1677 XmlDocument doc = new XmlDocument();
1296 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1678 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1297 1679
1298 SceneObjectPart[] parts = m_parts.GetArray(); 1680 SceneObjectPart[] parts = m_parts.GetArray();
1299 for (int i = 0; i < parts.Length; i++) 1681 for (int i = 0; i < parts.Length; i++)
1300 { 1682 {
1301 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1683 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1302 foreach (KeyValuePair<UUID, string> kvp in pstates) 1684 foreach (KeyValuePair<UUID, string> kvp in pstates)
1303 states.Add(kvp.Key, kvp.Value); 1685 states[kvp.Key] = kvp.Value;
1304 } 1686 }
1305 1687
1306 if (states.Count > 0) 1688 if (states.Count > 0)
@@ -1319,6 +1701,130 @@ namespace OpenSim.Region.Framework.Scenes
1319 } 1701 }
1320 } 1702 }
1321 1703
1704 /// <summary>
1705 /// Attach this scene object to the given avatar.
1706 /// </summary>
1707 /// <param name="agentID"></param>
1708 /// <param name="attachmentpoint"></param>
1709 /// <param name="AttachOffset"></param>
1710 private void AttachToAgent(
1711 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1712 {
1713 if (avatar != null)
1714 {
1715 // don't attach attachments to child agents
1716 if (avatar.IsChildAgent) return;
1717
1718 // Remove from database and parcel prim count
1719 m_scene.DeleteFromStorage(so.UUID);
1720 m_scene.EventManager.TriggerParcelPrimCountTainted();
1721
1722 so.AttachedAvatar = avatar.UUID;
1723
1724 if (so.RootPart.PhysActor != null)
1725 {
1726 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1727 so.RootPart.PhysActor = null;
1728 }
1729
1730 so.AbsolutePosition = attachOffset;
1731 so.RootPart.AttachedPos = attachOffset;
1732 so.IsAttachment = true;
1733 so.RootPart.SetParentLocalId(avatar.LocalId);
1734 so.AttachmentPoint = attachmentpoint;
1735
1736 avatar.AddAttachment(this);
1737
1738 if (!silent)
1739 {
1740 // Killing it here will cause the client to deselect it
1741 // It then reappears on the avatar, deselected
1742 // through the full update below
1743 //
1744 if (IsSelected)
1745 {
1746 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1747 }
1748
1749 IsSelected = false; // fudge....
1750 ScheduleGroupForFullUpdate();
1751 }
1752 }
1753 else
1754 {
1755 m_log.WarnFormat(
1756 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1757 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1758 }
1759 }
1760
1761 public byte GetAttachmentPoint()
1762 {
1763 return m_rootPart.Shape.State;
1764 }
1765
1766 public void DetachToGround()
1767 {
1768 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1769 if (avatar == null)
1770 return;
1771 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1772 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1773 avatar.RemoveAttachment(this);
1774
1775 Vector3 detachedpos = new Vector3(127f,127f,127f);
1776 if (avatar == null)
1777 return;
1778
1779 detachedpos = avatar.AbsolutePosition;
1780 FromItemID = UUID.Zero;
1781
1782 AbsolutePosition = detachedpos;
1783 AttachedAvatar = UUID.Zero;
1784
1785 //SceneObjectPart[] parts = m_parts.GetArray();
1786 //for (int i = 0; i < parts.Length; i++)
1787 // parts[i].AttachedAvatar = UUID.Zero;
1788
1789 m_rootPart.SetParentLocalId(0);
1790 AttachmentPoint = (byte)0;
1791 // must check if buildind should be true or false here
1792// m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1793 ApplyPhysics();
1794
1795 HasGroupChanged = true;
1796 RootPart.Rezzed = DateTime.Now;
1797 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1798 AttachToBackup();
1799 m_scene.EventManager.TriggerParcelPrimCountTainted();
1800 m_rootPart.ScheduleFullUpdate();
1801 m_rootPart.ClearUndoState();
1802 }
1803
1804 public void DetachToInventoryPrep()
1805 {
1806 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1807 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1808 if (avatar != null)
1809 {
1810 //detachedpos = avatar.AbsolutePosition;
1811 avatar.RemoveAttachment(this);
1812 }
1813
1814 AttachedAvatar = UUID.Zero;
1815
1816 /*SceneObjectPart[] parts = m_parts.GetArray();
1817 for (int i = 0; i < parts.Length; i++)
1818 parts[i].AttachedAvatar = UUID.Zero;*/
1819
1820 m_rootPart.SetParentLocalId(0);
1821 //m_rootPart.SetAttachmentPoint((byte)0);
1822 IsAttachment = false;
1823 AbsolutePosition = m_rootPart.AttachedPos;
1824 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1825 //AttachToBackup();
1826 //m_rootPart.ScheduleFullUpdate();
1827 }
1322 1828
1323 /// <summary> 1829 /// <summary>
1324 /// 1830 ///
@@ -1360,7 +1866,10 @@ namespace OpenSim.Region.Framework.Scenes
1360 public void AddPart(SceneObjectPart part) 1866 public void AddPart(SceneObjectPart part)
1361 { 1867 {
1362 part.SetParent(this); 1868 part.SetParent(this);
1363 part.LinkNum = m_parts.Add(part.UUID, part); 1869 m_parts.Add(part.UUID, part);
1870
1871 part.LinkNum = m_parts.Count;
1872
1364 if (part.LinkNum == 2) 1873 if (part.LinkNum == 2)
1365 RootPart.LinkNum = 1; 1874 RootPart.LinkNum = 1;
1366 } 1875 }
@@ -1386,6 +1895,14 @@ namespace OpenSim.Region.Framework.Scenes
1386 parts[i].UUID = UUID.Random(); 1895 parts[i].UUID = UUID.Random();
1387 } 1896 }
1388 1897
1898 // helper provided for parts.
1899 public int GetSceneMaxUndo()
1900 {
1901 if (m_scene != null)
1902 return m_scene.MaxUndoCount;
1903 return 5;
1904 }
1905
1389 // justincc: I don't believe this hack is needed any longer, especially since the physics 1906 // justincc: I don't believe this hack is needed any longer, especially since the physics
1390 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false 1907 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
1391 // this method was preventing proper reload of scene objects. 1908 // this method was preventing proper reload of scene objects.
@@ -1407,11 +1924,21 @@ namespace OpenSim.Region.Framework.Scenes
1407 // Setting this SOG's absolute position also loops through and sets the positions 1924 // Setting this SOG's absolute position also loops through and sets the positions
1408 // of the SOP's in this SOG's linkset. This has the side affect of making sure 1925 // of the SOP's in this SOG's linkset. This has the side affect of making sure
1409 // the physics world matches the simulated world. 1926 // the physics world matches the simulated world.
1410 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 1927 // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1411 1928
1412 // teravus: AbsolutePosition is NOT a normal property! 1929 // teravus: AbsolutePosition is NOT a normal property!
1413 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 1930 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1414 // jhurliman: Then why is it a property instead of two methods? 1931 // jhurliman: Then why is it a property instead of two methods?
1932
1933 // do only what is supposed to do
1934 Vector3 groupPosition = m_rootPart.GroupPosition;
1935 SceneObjectPart[] parts = m_parts.GetArray();
1936
1937 foreach (SceneObjectPart part in parts)
1938 {
1939 if (part != m_rootPart)
1940 part.GroupPosition = groupPosition;
1941 }
1415 } 1942 }
1416 1943
1417 public UUID GetPartsFullID(uint localID) 1944 public UUID GetPartsFullID(uint localID)
@@ -1443,7 +1970,7 @@ namespace OpenSim.Region.Framework.Scenes
1443// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1970// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1444// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1971// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1445 1972
1446 part.StoreUndoState(); 1973// part.StoreUndoState();
1447 part.OnGrab(offsetPos, remoteClient); 1974 part.OnGrab(offsetPos, remoteClient);
1448 } 1975 }
1449 1976
@@ -1463,28 +1990,36 @@ namespace OpenSim.Region.Framework.Scenes
1463 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1990 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1464 public void DeleteGroupFromScene(bool silent) 1991 public void DeleteGroupFromScene(bool silent)
1465 { 1992 {
1993 // We need to keep track of this state in case this group is still queued for backup.
1994 IsDeleted = true;
1995
1996 DetachFromBackup();
1997
1466 SceneObjectPart[] parts = m_parts.GetArray(); 1998 SceneObjectPart[] parts = m_parts.GetArray();
1467 for (int i = 0; i < parts.Length; i++) 1999 for (int i = 0; i < parts.Length; i++)
1468 { 2000 {
1469 SceneObjectPart part = parts[i]; 2001 SceneObjectPart part = parts[i];
1470 2002
1471 Scene.ForEachScenePresence(sp => 2003 if (Scene != null)
1472 { 2004 {
1473 if (!sp.IsChildAgent && sp.ParentID == part.LocalId) 2005 Scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
1474 sp.StandUp();
1475
1476 if (!silent)
1477 { 2006 {
1478 part.ClearUpdateSchedule(); 2007 if (avatar.ParentID == LocalId)
1479 if (part == m_rootPart) 2008 avatar.StandUp();
2009
2010 if (!silent)
1480 { 2011 {
1481 if (!IsAttachment 2012 part.ClearUpdateSchedule();
1482 || AttachedAvatar == sp.UUID 2013 if (part == m_rootPart)
1483 || !HasPrivateAttachmentPoint) 2014 {
1484 sp.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); 2015 if (!IsAttachment
2016 || AttachedAvatar == avatar.ControllingClient.AgentId
2017 || !HasPrivateAttachmentPoint)
2018 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
2019 }
1485 } 2020 }
1486 } 2021 });
1487 }); 2022 }
1488 } 2023 }
1489 } 2024 }
1490 2025
@@ -1555,28 +2090,43 @@ namespace OpenSim.Region.Framework.Scenes
1555 /// </summary> 2090 /// </summary>
1556 public void ApplyPhysics() 2091 public void ApplyPhysics()
1557 { 2092 {
1558 // Apply physics to the root prim
1559 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1560
1561 // Apply physics to child prims
1562 SceneObjectPart[] parts = m_parts.GetArray(); 2093 SceneObjectPart[] parts = m_parts.GetArray();
1563 if (parts.Length > 1) 2094 if (parts.Length > 1)
1564 { 2095 {
2096 ResetChildPrimPhysicsPositions();
2097
2098 // Apply physics to the root prim
2099 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
2100
2101
1565 for (int i = 0; i < parts.Length; i++) 2102 for (int i = 0; i < parts.Length; i++)
1566 { 2103 {
1567 SceneObjectPart part = parts[i]; 2104 SceneObjectPart part = parts[i];
1568 if (part.LocalId != m_rootPart.LocalId) 2105 if (part.LocalId != m_rootPart.LocalId)
1569 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 2106 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1570 } 2107 }
1571
1572 // Hack to get the physics scene geometries in the right spot 2108 // Hack to get the physics scene geometries in the right spot
1573 ResetChildPrimPhysicsPositions(); 2109// ResetChildPrimPhysicsPositions();
2110 if (m_rootPart.PhysActor != null)
2111 {
2112 m_rootPart.PhysActor.Building = false;
2113 }
2114 }
2115 else
2116 {
2117 // Apply physics to the root prim
2118 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1574 } 2119 }
1575 } 2120 }
1576 2121
1577 public void SetOwnerId(UUID userId) 2122 public void SetOwnerId(UUID userId)
1578 { 2123 {
1579 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 2124 ForEachPart(delegate(SceneObjectPart part)
2125 {
2126
2127 part.OwnerID = userId;
2128
2129 });
1580 } 2130 }
1581 2131
1582 public void ForEachPart(Action<SceneObjectPart> whatToDo) 2132 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1601,18 +2151,24 @@ namespace OpenSim.Region.Framework.Scenes
1601 return; 2151 return;
1602 } 2152 }
1603 2153
1604 if (IsDeleted || UUID == UUID.Zero) 2154 if (IsDeleted || inTransit || UUID == UUID.Zero)
1605 { 2155 {
1606// m_log.DebugFormat( 2156// m_log.DebugFormat(
1607// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); 2157// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID);
1608 return; 2158 return;
1609 } 2159 }
1610 2160
2161 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
2162 return;
2163
1611 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 2164 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1612 // any exception propogate upwards. 2165 // any exception propogate upwards.
1613 try 2166 try
1614 { 2167 {
1615 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 2168 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
2169 !m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things
2170 m_scene.LoadingPrims) // Land may not be valid yet
2171
1616 { 2172 {
1617 ILandObject parcel = m_scene.LandChannel.GetLandObject( 2173 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1618 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 2174 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1639,6 +2195,7 @@ namespace OpenSim.Region.Framework.Scenes
1639 } 2195 }
1640 } 2196 }
1641 } 2197 }
2198
1642 } 2199 }
1643 2200
1644 if (m_scene.UseBackup && HasGroupChanged) 2201 if (m_scene.UseBackup && HasGroupChanged)
@@ -1646,10 +2203,31 @@ namespace OpenSim.Region.Framework.Scenes
1646 // don't backup while it's selected or you're asking for changes mid stream. 2203 // don't backup while it's selected or you're asking for changes mid stream.
1647 if (isTimeToPersist() || forcedBackup) 2204 if (isTimeToPersist() || forcedBackup)
1648 { 2205 {
2206 if (m_rootPart.PhysActor != null &&
2207 (!m_rootPart.PhysActor.IsPhysical))
2208 {
2209 // Possible ghost prim
2210 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
2211 {
2212 foreach (SceneObjectPart part in m_parts.GetArray())
2213 {
2214 // Re-set physics actor positions and
2215 // orientations
2216 part.GroupPosition = m_rootPart.GroupPosition;
2217 }
2218 }
2219 }
1649// m_log.DebugFormat( 2220// m_log.DebugFormat(
1650// "[SCENE]: Storing {0}, {1} in {2}", 2221// "[SCENE]: Storing {0}, {1} in {2}",
1651// Name, UUID, m_scene.RegionInfo.RegionName); 2222// Name, UUID, m_scene.RegionInfo.RegionName);
1652 2223
2224 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2225 {
2226 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2227 RootPart.Shape.State = 0;
2228 ScheduleGroupForFullUpdate();
2229 }
2230
1653 SceneObjectGroup backup_group = Copy(false); 2231 SceneObjectGroup backup_group = Copy(false);
1654 backup_group.RootPart.Velocity = RootPart.Velocity; 2232 backup_group.RootPart.Velocity = RootPart.Velocity;
1655 backup_group.RootPart.Acceleration = RootPart.Acceleration; 2233 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1659,13 +2237,22 @@ namespace OpenSim.Region.Framework.Scenes
1659 GroupContainsForeignPrims = false; 2237 GroupContainsForeignPrims = false;
1660 2238
1661 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2239 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2240
1662 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 2241 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
1663 2242
1664 backup_group.ForEachPart(delegate(SceneObjectPart part) 2243 backup_group.ForEachPart(delegate(SceneObjectPart part)
1665 { 2244 {
1666 part.Inventory.ProcessInventoryBackup(datastore); 2245 part.Inventory.ProcessInventoryBackup(datastore);
2246
2247 // take the change to delete things
2248 if(part.KeyframeMotion != null)
2249 {
2250 part.KeyframeMotion.Delete();
2251 part.KeyframeMotion = null;
2252 }
1667 }); 2253 });
1668 2254
2255
1669 backup_group = null; 2256 backup_group = null;
1670 } 2257 }
1671// else 2258// else
@@ -1715,26 +2302,34 @@ namespace OpenSim.Region.Framework.Scenes
1715 /// <returns></returns> 2302 /// <returns></returns>
1716 public SceneObjectGroup Copy(bool userExposed) 2303 public SceneObjectGroup Copy(bool userExposed)
1717 { 2304 {
1718 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2305 m_dupeInProgress = true;
1719 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1720 // but not between regions on different simulators). Really, all copying should be done explicitly.
1721 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2306 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
2307 dupe.m_isBackedUp = false;
2308 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1722 2309
2310 // a copy isnt backedup
1723 dupe.Backup = false; 2311 dupe.Backup = false;
1724 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2312 dupe.m_isBackedUp = false;
2313
2314 // a copy is not in transit hopefully
2315 dupe.inTransit = false;
2316
2317 // new group as no sitting avatars
1725 dupe.m_sittingAvatars = new List<ScenePresence>(); 2318 dupe.m_sittingAvatars = new List<ScenePresence>();
2319
1726 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 2320 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1727 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 2321 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
2322
1728 2323
1729 if (userExposed) 2324 if (userExposed)
1730 dupe.m_rootPart.TrimPermissions(); 2325 dupe.m_rootPart.TrimPermissions();
1731 2326
1732 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2327 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1733 2328
1734 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2329 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1735 { 2330 {
1736 return p1.LinkNum.CompareTo(p2.LinkNum); 2331 return p1.LinkNum.CompareTo(p2.LinkNum);
1737 } 2332 }
1738 ); 2333 );
1739 2334
1740 foreach (SceneObjectPart part in partList) 2335 foreach (SceneObjectPart part in partList)
@@ -1744,43 +2339,56 @@ namespace OpenSim.Region.Framework.Scenes
1744 { 2339 {
1745 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2340 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1746 newPart.LinkNum = part.LinkNum; 2341 newPart.LinkNum = part.LinkNum;
1747 } 2342// if (userExposed)
2343 newPart.ParentID = dupe.m_rootPart.LocalId;
2344 }
1748 else 2345 else
1749 { 2346 {
1750 newPart = dupe.m_rootPart; 2347 newPart = dupe.m_rootPart;
1751 } 2348 }
2349/*
2350 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2351 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1752 2352
1753 // Need to duplicate the physics actor as well 2353 // Need to duplicate the physics actor as well
1754 PhysicsActor originalPartPa = part.PhysActor; 2354 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1755 if (originalPartPa != null && userExposed)
1756 { 2355 {
1757 PrimitiveBaseShape pbs = newPart.Shape; 2356 PrimitiveBaseShape pbs = newPart.Shape;
1758
1759 newPart.PhysActor 2357 newPart.PhysActor
1760 = m_scene.PhysicsScene.AddPrimShape( 2358 = m_scene.PhysicsScene.AddPrimShape(
1761 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2359 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1762 pbs, 2360 pbs,
1763 newPart.AbsolutePosition, 2361 newPart.AbsolutePosition,
1764 newPart.Scale, 2362 newPart.Scale,
1765 newPart.RotationOffset, 2363 newPart.GetWorldRotation(),
1766 originalPartPa.IsPhysical, 2364 isphys,
2365 isphan,
1767 newPart.LocalId); 2366 newPart.LocalId);
1768 2367
1769 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2368 newPart.DoPhysicsPropertyUpdate(isphys, true);
1770 } 2369 */
2370 if (userExposed)
2371 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2372// }
2373 // copy keyframemotion
1771 if (part.KeyframeMotion != null) 2374 if (part.KeyframeMotion != null)
1772 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe); 2375 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe);
1773 } 2376 }
1774 2377
1775 if (userExposed) 2378 if (userExposed)
1776 { 2379 {
1777 dupe.UpdateParentIDs(); 2380// done above dupe.UpdateParentIDs();
2381
2382 if (dupe.m_rootPart.PhysActor != null)
2383 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2384
1778 dupe.HasGroupChanged = true; 2385 dupe.HasGroupChanged = true;
1779 dupe.AttachToBackup(); 2386 dupe.AttachToBackup();
1780 2387
1781 ScheduleGroupForFullUpdate(); 2388 ScheduleGroupForFullUpdate();
1782 } 2389 }
1783 2390
2391 m_dupeInProgress = false;
1784 return dupe; 2392 return dupe;
1785 } 2393 }
1786 2394
@@ -1792,7 +2400,13 @@ namespace OpenSim.Region.Framework.Scenes
1792 /// <param name="cGroupID"></param> 2400 /// <param name="cGroupID"></param>
1793 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2401 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1794 { 2402 {
1795 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2403 SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed);
2404// SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2405// newpart.LocalId = m_scene.AllocateLocalId();
2406
2407 SetRootPart(newpart);
2408 if (userExposed)
2409 RootPart.Velocity = Vector3.Zero; // In case source is moving
1796 } 2410 }
1797 2411
1798 public void ScriptSetPhysicsStatus(bool usePhysics) 2412 public void ScriptSetPhysicsStatus(bool usePhysics)
@@ -1850,13 +2464,14 @@ namespace OpenSim.Region.Framework.Scenes
1850 2464
1851 if (pa != null) 2465 if (pa != null)
1852 { 2466 {
1853 pa.AddForce(impulse, true); 2467 // false to be applied as a impulse
2468 pa.AddForce(impulse, false);
1854 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2469 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1855 } 2470 }
1856 } 2471 }
1857 } 2472 }
1858 2473
1859 public void applyAngularImpulse(Vector3 impulse) 2474 public void ApplyAngularImpulse(Vector3 impulse)
1860 { 2475 {
1861 PhysicsActor pa = RootPart.PhysActor; 2476 PhysicsActor pa = RootPart.PhysActor;
1862 2477
@@ -1864,21 +2479,8 @@ namespace OpenSim.Region.Framework.Scenes
1864 { 2479 {
1865 if (!IsAttachment) 2480 if (!IsAttachment)
1866 { 2481 {
1867 pa.AddAngularForce(impulse, true); 2482 // false to be applied as a impulse
1868 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2483 pa.AddAngularForce(impulse, false);
1869 }
1870 }
1871 }
1872
1873 public void setAngularImpulse(Vector3 impulse)
1874 {
1875 PhysicsActor pa = RootPart.PhysActor;
1876
1877 if (pa != null)
1878 {
1879 if (!IsAttachment)
1880 {
1881 pa.Torque = impulse;
1882 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2484 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1883 } 2485 }
1884 } 2486 }
@@ -1886,20 +2488,10 @@ namespace OpenSim.Region.Framework.Scenes
1886 2488
1887 public Vector3 GetTorque() 2489 public Vector3 GetTorque()
1888 { 2490 {
1889 PhysicsActor pa = RootPart.PhysActor; 2491 return RootPart.Torque;
1890
1891 if (pa != null)
1892 {
1893 if (!IsAttachment)
1894 {
1895 Vector3 torque = pa.Torque;
1896 return torque;
1897 }
1898 }
1899
1900 return Vector3.Zero;
1901 } 2492 }
1902 2493
2494 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1903 public void MoveToTarget(Vector3 target, float tau) 2495 public void MoveToTarget(Vector3 target, float tau)
1904 { 2496 {
1905 if (IsAttachment) 2497 if (IsAttachment)
@@ -1929,21 +2521,61 @@ namespace OpenSim.Region.Framework.Scenes
1929 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 2521 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1930 2522
1931 if (avatar != null) 2523 if (avatar != null)
2524 {
1932 avatar.ResetMoveToTarget(); 2525 avatar.ResetMoveToTarget();
2526 }
1933 } 2527 }
1934 else 2528 else
1935 { 2529 {
1936 PhysicsActor pa = RootPart.PhysActor; 2530 PhysicsActor pa = RootPart.PhysActor;
1937 2531
1938 if (pa != null && pa.PIDActive) 2532 if (pa != null)
1939 {
1940 pa.PIDActive = false; 2533 pa.PIDActive = false;
1941 2534
1942 ScheduleGroupForTerseUpdate(); 2535 RootPart.ScheduleTerseUpdate(); // send a stop information
2536 }
2537 }
2538
2539 public void rotLookAt(Quaternion target, float strength, float damping)
2540 {
2541 SceneObjectPart rootpart = m_rootPart;
2542 if (rootpart != null)
2543 {
2544 if (IsAttachment)
2545 {
2546 /*
2547 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2548 if (avatar != null)
2549 {
2550 Rotate the Av?
2551 } */
2552 }
2553 else
2554 {
2555 if (rootpart.PhysActor != null)
2556 { // APID must be implemented in your physics system for this to function.
2557 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2558 rootpart.PhysActor.APIDStrength = strength;
2559 rootpart.PhysActor.APIDDamping = damping;
2560 rootpart.PhysActor.APIDActive = true;
2561 }
1943 } 2562 }
1944 } 2563 }
1945 } 2564 }
2565
2566 public void stopLookAt()
2567 {
2568 SceneObjectPart rootpart = m_rootPart;
2569 if (rootpart != null)
2570 {
2571 if (rootpart.PhysActor != null)
2572 { // APID must be implemented in your physics system for this to function.
2573 rootpart.PhysActor.APIDActive = false;
2574 }
2575 }
1946 2576
2577 }
2578
1947 /// <summary> 2579 /// <summary>
1948 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2580 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1949 /// </summary> 2581 /// </summary>
@@ -1952,7 +2584,15 @@ namespace OpenSim.Region.Framework.Scenes
1952 /// <param name="tau">Number of seconds over which to reach target</param> 2584 /// <param name="tau">Number of seconds over which to reach target</param>
1953 public void SetHoverHeight(float height, PIDHoverType hoverType, float tau) 2585 public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
1954 { 2586 {
1955 PhysicsActor pa = RootPart.PhysActor; 2587 PhysicsActor pa = null;
2588 if(IsAttachment)
2589 {
2590 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
2591 if (avatar != null)
2592 pa = avatar.PhysicsActor;
2593 }
2594 else
2595 pa = RootPart.PhysActor;
1956 2596
1957 if (pa != null) 2597 if (pa != null)
1958 { 2598 {
@@ -1960,7 +2600,7 @@ namespace OpenSim.Region.Framework.Scenes
1960 { 2600 {
1961 pa.PIDHoverHeight = height; 2601 pa.PIDHoverHeight = height;
1962 pa.PIDHoverType = hoverType; 2602 pa.PIDHoverType = hoverType;
1963 pa.PIDTau = tau; 2603 pa.PIDHoverTau = tau;
1964 pa.PIDHoverActive = true; 2604 pa.PIDHoverActive = true;
1965 } 2605 }
1966 else 2606 else
@@ -2001,6 +2641,9 @@ namespace OpenSim.Region.Framework.Scenes
2001 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2641 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2002 { 2642 {
2003 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2643 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2644// SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2645// newPart.LocalId = m_scene.AllocateLocalId();
2646
2004 AddPart(newPart); 2647 AddPart(newPart);
2005 2648
2006 SetPartAsNonRoot(newPart); 2649 SetPartAsNonRoot(newPart);
@@ -2050,6 +2693,7 @@ namespace OpenSim.Region.Framework.Scenes
2050 2693
2051 #endregion 2694 #endregion
2052 2695
2696
2053 public override void Update() 2697 public override void Update()
2054 { 2698 {
2055 // Check that the group was not deleted before the scheduled update 2699 // Check that the group was not deleted before the scheduled update
@@ -2057,7 +2701,7 @@ namespace OpenSim.Region.Framework.Scenes
2057 // an object has been deleted from a scene before update was processed. 2701 // an object has been deleted from a scene before update was processed.
2058 // A more fundamental overhaul of the update mechanism is required to eliminate all 2702 // A more fundamental overhaul of the update mechanism is required to eliminate all
2059 // the race conditions. 2703 // the race conditions.
2060 if (IsDeleted) 2704 if (IsDeleted || inTransit)
2061 return; 2705 return;
2062 2706
2063 // Even temporary objects take part in physics (e.g. temp-on-rez bullets) 2707 // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@@ -2068,18 +2712,17 @@ namespace OpenSim.Region.Framework.Scenes
2068 // check to see if the physical position or rotation warrant an update. 2712 // check to see if the physical position or rotation warrant an update.
2069 if (m_rootPart.UpdateFlag == UpdateRequired.NONE) 2713 if (m_rootPart.UpdateFlag == UpdateRequired.NONE)
2070 { 2714 {
2071 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2715 // rootpart SendScheduledUpdates will check if a update is needed
2072 2716 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2073 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) 2717 }
2074 {
2075 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2076 lastPhysGroupPos = AbsolutePosition;
2077 }
2078 2718
2079 if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) 2719 if (IsAttachment)
2720 {
2721 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2722 if (sp != null)
2080 { 2723 {
2081 m_rootPart.UpdateFlag = UpdateRequired.TERSE; 2724 sp.SendAttachmentScheduleUpdate(this);
2082 lastPhysGroupRot = GroupRotation; 2725 return;
2083 } 2726 }
2084 } 2727 }
2085 2728
@@ -2139,20 +2782,30 @@ namespace OpenSim.Region.Framework.Scenes
2139 /// Immediately send a full update for this scene object. 2782 /// Immediately send a full update for this scene object.
2140 /// </summary> 2783 /// </summary>
2141 public void SendGroupFullUpdate() 2784 public void SendGroupFullUpdate()
2142 { 2785 {
2143 if (IsDeleted) 2786 if (IsDeleted)
2144 return; 2787 return;
2145 2788
2146// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2789// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2147 2790
2148 RootPart.SendFullUpdateToAllClients(); 2791 if (IsAttachment)
2792 {
2793 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2794 if (sp != null)
2795 {
2796 sp.SendAttachmentUpdate(this,UpdateRequired.FULL);
2797 return;
2798 }
2799 }
2800
2801 RootPart.SendFullUpdateToAllClientsInternal();
2149 2802
2150 SceneObjectPart[] parts = m_parts.GetArray(); 2803 SceneObjectPart[] parts = m_parts.GetArray();
2151 for (int i = 0; i < parts.Length; i++) 2804 for (int i = 0; i < parts.Length; i++)
2152 { 2805 {
2153 SceneObjectPart part = parts[i]; 2806 SceneObjectPart part = parts[i];
2154 if (part != RootPart) 2807 if (part != RootPart)
2155 part.SendFullUpdateToAllClients(); 2808 part.SendFullUpdateToAllClientsInternal();
2156 } 2809 }
2157 } 2810 }
2158 2811
@@ -2164,7 +2817,7 @@ namespace OpenSim.Region.Framework.Scenes
2164 /// </summary> 2817 /// </summary>
2165 public void SendGroupRootTerseUpdate() 2818 public void SendGroupRootTerseUpdate()
2166 { 2819 {
2167 if (IsDeleted) 2820 if (IsDeleted || inTransit)
2168 return; 2821 return;
2169 2822
2170 RootPart.SendTerseUpdateToAllClients(); 2823 RootPart.SendTerseUpdateToAllClients();
@@ -2183,12 +2836,22 @@ namespace OpenSim.Region.Framework.Scenes
2183 /// </summary> 2836 /// </summary>
2184 public void SendGroupTerseUpdate() 2837 public void SendGroupTerseUpdate()
2185 { 2838 {
2186 if (IsDeleted) 2839 if (IsDeleted || inTransit)
2187 return; 2840 return;
2188 2841
2842 if (IsAttachment)
2843 {
2844 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2845 if (sp != null)
2846 {
2847 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
2848 return;
2849 }
2850 }
2851
2189 SceneObjectPart[] parts = m_parts.GetArray(); 2852 SceneObjectPart[] parts = m_parts.GetArray();
2190 for (int i = 0; i < parts.Length; i++) 2853 for (int i = 0; i < parts.Length; i++)
2191 parts[i].SendTerseUpdateToAllClients(); 2854 parts[i].SendTerseUpdateToAllClientsInternal();
2192 } 2855 }
2193 2856
2194 /// <summary> 2857 /// <summary>
@@ -2296,9 +2959,41 @@ namespace OpenSim.Region.Framework.Scenes
2296 return; 2959 return;
2297 } 2960 }
2298 2961
2962 // physical prims count limit
2963 // not very eficient :(
2964
2965 if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) >
2966 m_scene.m_linksetPhysCapacity)
2967 {
2968 int cntr = 0;
2969 foreach (SceneObjectPart part in Parts)
2970 {
2971 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2972 cntr++;
2973 }
2974 foreach (SceneObjectPart part in objectGroup.Parts)
2975 {
2976 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2977 cntr++;
2978 }
2979
2980 if (cntr > m_scene.m_linksetPhysCapacity)
2981 {
2982 // cancel physics
2983 RootPart.Flags &= ~PrimFlags.Physics;
2984 ApplyPhysics();
2985 }
2986 }
2987
2988
2299 // 'linkPart' == the root of the group being linked into this group 2989 // 'linkPart' == the root of the group being linked into this group
2300 SceneObjectPart linkPart = objectGroup.m_rootPart; 2990 SceneObjectPart linkPart = objectGroup.m_rootPart;
2301 2991
2992 if (m_rootPart.PhysActor != null)
2993 m_rootPart.PhysActor.Building = true;
2994 if (linkPart.PhysActor != null)
2995 linkPart.PhysActor.Building = true;
2996
2302 // physics flags from group to be applied to linked parts 2997 // physics flags from group to be applied to linked parts
2303 bool grpusephys = UsesPhysics; 2998 bool grpusephys = UsesPhysics;
2304 bool grptemporary = IsTemporary; 2999 bool grptemporary = IsTemporary;
@@ -2315,22 +3010,24 @@ namespace OpenSim.Region.Framework.Scenes
2315 // First move the new group's root SOP's position to be relative to ours 3010 // First move the new group's root SOP's position to be relative to ours
2316 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, 3011 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not,
2317 // this code can be reordered to have a more logical flow.) 3012 // this code can be reordered to have a more logical flow.)
2318 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 3013 linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition);
2319 // Assign the new parent to the root of the old group 3014 // Assign the new parent to the root of the old group
2320 linkPart.ParentID = m_rootPart.LocalId; 3015 linkPart.ParentID = m_rootPart.LocalId;
2321 // Now that it's a child, it's group position is our root position 3016 // Now that it's a child, it's group position is our root position
2322 linkPart.GroupPosition = AbsolutePosition; 3017 linkPart.setGroupPosition(AbsolutePosition);
2323 3018
2324 Vector3 axPos = linkPart.OffsetPosition;
2325 // Rotate the linking root SOP's position to be relative to the new root prim 3019 // Rotate the linking root SOP's position to be relative to the new root prim
2326 Quaternion parentRot = m_rootPart.RotationOffset; 3020 Quaternion parentRot = m_rootPart.RotationOffset;
2327 axPos *= Quaternion.Inverse(parentRot);
2328 linkPart.OffsetPosition = axPos;
2329 3021
2330 // Make the linking root SOP's rotation relative to the new root prim 3022 // Make the linking root SOP's rotation relative to the new root prim
2331 Quaternion oldRot = linkPart.RotationOffset; 3023 Quaternion oldRot = linkPart.RotationOffset;
2332 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3024 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2333 linkPart.RotationOffset = newRot; 3025 linkPart.setRotationOffset(newRot);
3026
3027 Vector3 axPos = linkPart.OffsetPosition;
3028 axPos *= Quaternion.Conjugate(parentRot);
3029 linkPart.OffsetPosition = axPos;
3030
2334 3031
2335 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. 3032 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset.
2336 // Now that we know this SOG has at least two SOPs in it, the new root 3033 // Now that we know this SOG has at least two SOPs in it, the new root
@@ -2360,10 +3057,12 @@ namespace OpenSim.Region.Framework.Scenes
2360 m_parts.Add(linkPart.UUID, linkPart); 3057 m_parts.Add(linkPart.UUID, linkPart);
2361 3058
2362 linkPart.SetParent(this); 3059 linkPart.SetParent(this);
3060 m_scene.updateScenePartGroup(linkPart, this);
3061
2363 linkPart.CreateSelected = true; 3062 linkPart.CreateSelected = true;
2364 3063
2365 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 3064 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2366 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); 3065 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2367 3066
2368 // If the added SOP is physical, also tell the physics engine about the link relationship. 3067 // If the added SOP is physical, also tell the physics engine about the link relationship.
2369 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3068 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2373,6 +3072,7 @@ namespace OpenSim.Region.Framework.Scenes
2373 } 3072 }
2374 3073
2375 linkPart.LinkNum = linkNum++; 3074 linkPart.LinkNum = linkNum++;
3075 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2376 3076
2377 // Get a list of the SOP's in the old group in order of their linknum's. 3077 // Get a list of the SOP's in the old group in order of their linknum's.
2378 SceneObjectPart[] ogParts = objectGroup.Parts; 3078 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2391,7 +3091,7 @@ namespace OpenSim.Region.Framework.Scenes
2391 3091
2392 // Update the physics flags for the newly added SOP 3092 // Update the physics flags for the newly added SOP
2393 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??) 3093 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??)
2394 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); 3094 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2395 3095
2396 // If the added SOP is physical, also tell the physics engine about the link relationship. 3096 // If the added SOP is physical, also tell the physics engine about the link relationship.
2397 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3097 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2409,7 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes
2409 objectGroup.IsDeleted = true; 3109 objectGroup.IsDeleted = true;
2410 3110
2411 objectGroup.m_parts.Clear(); 3111 objectGroup.m_parts.Clear();
2412 3112
2413 // Can't do this yet since backup still makes use of the root part without any synchronization 3113 // Can't do this yet since backup still makes use of the root part without any synchronization
2414// objectGroup.m_rootPart = null; 3114// objectGroup.m_rootPart = null;
2415 3115
@@ -2425,6 +3125,9 @@ namespace OpenSim.Region.Framework.Scenes
2425 // unmoved prims! 3125 // unmoved prims!
2426 ResetChildPrimPhysicsPositions(); 3126 ResetChildPrimPhysicsPositions();
2427 3127
3128 if (m_rootPart.PhysActor != null)
3129 m_rootPart.PhysActor.Building = false;
3130
2428 //HasGroupChanged = true; 3131 //HasGroupChanged = true;
2429 //ScheduleGroupForFullUpdate(); 3132 //ScheduleGroupForFullUpdate();
2430 } 3133 }
@@ -2492,7 +3195,10 @@ namespace OpenSim.Region.Framework.Scenes
2492// m_log.DebugFormat( 3195// m_log.DebugFormat(
2493// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 3196// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2494// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 3197// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2495 3198
3199 if (m_rootPart.PhysActor != null)
3200 m_rootPart.PhysActor.Building = true;
3201
2496 linkPart.ClearUndoState(); 3202 linkPart.ClearUndoState();
2497 3203
2498 Vector3 worldPos = linkPart.GetWorldPosition(); 3204 Vector3 worldPos = linkPart.GetWorldPosition();
@@ -2547,30 +3253,31 @@ namespace OpenSim.Region.Framework.Scenes
2547 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; 3253 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
2548 linkPart.OffsetPosition = new Vector3(0, 0, 0); 3254 linkPart.OffsetPosition = new Vector3(0, 0, 0);
2549 */ 3255 */
2550 linkPart.GroupPosition = worldPos; 3256 linkPart.setGroupPosition(worldPos);
2551 linkPart.OffsetPosition = Vector3.Zero; 3257 linkPart.setOffsetPosition(Vector3.Zero);
2552 linkPart.RotationOffset = worldRot; 3258 linkPart.setRotationOffset(worldRot);
2553 3259
2554 // Create a new SOG to go around this unlinked and unattached SOP 3260 // Create a new SOG to go around this unlinked and unattached SOP
2555 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); 3261 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
2556 3262
2557 m_scene.AddNewSceneObject(objectGroup, true); 3263 m_scene.AddNewSceneObject(objectGroup, true);
2558 3264
2559 if (sendEvents)
2560 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2561
2562 linkPart.Rezzed = RootPart.Rezzed; 3265 linkPart.Rezzed = RootPart.Rezzed;
2563 3266
2564 // We must persist the delinked group to the database immediately, for safety. The problem 3267 // When we delete a group, we currently have to force persist to the database if the object id has changed
2565 // is that although in memory the new group has a new SceneGroupID, in the database it 3268 // (since delete works by deleting all rows which have a given object id)
2566 // still has the parent group's SceneGroupID (until the next backup). This means that if the 3269
2567 // parent group is deleted then the delinked group will also be deleted from the database. 3270 // this is as it seems to be in sl now
2568 // This problem will disappear if the region remains alive long enough for another backup, 3271 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2569 // since at that time the delinked group's new SceneGroupID will be written to the database. 3272 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2570 // But if the region crashes before that then the prims will be permanently gone, and this must 3273
2571 // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case 3274 if (m_rootPart.PhysActor != null)
2572 // because the delinked group doesn't know when the source group is deleted.) 3275 m_rootPart.PhysActor.Building = false;
2573 m_scene.ForceSceneObjectBackup(objectGroup); 3276
3277 objectGroup.HasGroupChangedDueToDelink = true;
3278
3279 if (sendEvents)
3280 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2574 3281
2575 return objectGroup; 3282 return objectGroup;
2576 } 3283 }
@@ -2581,7 +3288,9 @@ namespace OpenSim.Region.Framework.Scenes
2581 /// <param name="objectGroup"></param> 3288 /// <param name="objectGroup"></param>
2582 public virtual void DetachFromBackup() 3289 public virtual void DetachFromBackup()
2583 { 3290 {
2584 if (Backup && Scene != null) 3291 if (m_scene != null)
3292 m_scene.SceneGraph.FireDetachFromBackup(this);
3293 if (m_isBackedUp && Scene != null)
2585 m_scene.EventManager.OnBackup -= ProcessBackup; 3294 m_scene.EventManager.OnBackup -= ProcessBackup;
2586 3295
2587 Backup = false; 3296 Backup = false;
@@ -2597,14 +3306,14 @@ namespace OpenSim.Region.Framework.Scenes
2597 Quaternion parentRot = oldGroupRotation; 3306 Quaternion parentRot = oldGroupRotation;
2598 Quaternion oldRot = part.RotationOffset; 3307 Quaternion oldRot = part.RotationOffset;
2599 3308
2600 // Move our position to not be relative to the old parent 3309 // Move our position in world
2601 Vector3 axPos = part.OffsetPosition; 3310 Vector3 axPos = part.OffsetPosition;
2602 axPos *= parentRot; 3311 axPos *= parentRot;
2603 part.OffsetPosition = axPos; 3312 Vector3 newPos = oldGroupPosition + axPos;
2604 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 3313 part.setGroupPosition(newPos);
2605 part.OffsetPosition = Vector3.Zero; 3314 part.setOffsetPosition(Vector3.Zero);
2606 3315
2607 // Compution our rotation to be not relative to the old parent 3316 // Compution our rotation in world
2608 Quaternion worldRot = parentRot * oldRot; 3317 Quaternion worldRot = parentRot * oldRot;
2609 part.RotationOffset = worldRot; 3318 part.RotationOffset = worldRot;
2610 3319
@@ -2615,29 +3324,32 @@ namespace OpenSim.Region.Framework.Scenes
2615 3324
2616 part.LinkNum = linkNum; 3325 part.LinkNum = linkNum;
2617 3326
3327 m_scene.updateScenePartGroup(part, this);
3328
2618 // Compute the new position of this SOP relative to the group position 3329 // Compute the new position of this SOP relative to the group position
2619 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 3330 part.setOffsetPosition(newPos - AbsolutePosition);
2620 3331
2621 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. 3332 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times.
2622 // It would have the affect of setting the physics engine position multiple 3333 // It would have the affect of setting the physics engine position multiple
2623 // times. In theory, that is not necessary but I don't have a good linkset 3334 // times. In theory, that is not necessary but I don't have a good linkset
2624 // test to know that cleaning up this code wouldn't break things.) 3335 // test to know that cleaning up this code wouldn't break things.)
2625 3336
2626 // Rotate the relative position by the rotation of the group
2627 Quaternion rootRotation = m_rootPart.RotationOffset;
2628 Vector3 pos = part.OffsetPosition;
2629 pos *= Quaternion.Inverse(rootRotation);
2630 part.OffsetPosition = pos;
2631
2632 // Compute the SOP's rotation relative to the rotation of the group. 3337 // Compute the SOP's rotation relative to the rotation of the group.
2633 parentRot = m_rootPart.RotationOffset; 3338 parentRot = m_rootPart.RotationOffset;
3339
2634 oldRot = part.RotationOffset; 3340 oldRot = part.RotationOffset;
2635 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3341 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2636 part.RotationOffset = newRot; 3342 part.setRotationOffset(newRot);
3343
3344 Vector3 pos = part.OffsetPosition;
3345 pos *= Quaternion.Conjugate(parentRot);
3346
3347 part.OffsetPosition = pos; // update position and orientation on physics also
2637 3348
2638 // Since this SOP's state has changed, push those changes into the physics engine 3349 // Since this SOP's state has changed, push those changes into the physics engine
2639 // and the simulator. 3350 // and the simulator.
2640 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3351 // done on caller
3352// part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2641 } 3353 }
2642 3354
2643 /// <summary> 3355 /// <summary>
@@ -2665,10 +3377,14 @@ namespace OpenSim.Region.Framework.Scenes
2665 { 3377 {
2666 if (!BlockGrabOverride && !part.BlockGrab) 3378 if (!BlockGrabOverride && !part.BlockGrab)
2667 { 3379 {
2668 Vector3 llmoveforce = pos - AbsolutePosition; 3380/* Vector3 llmoveforce = pos - AbsolutePosition;
2669 Vector3 grabforce = llmoveforce; 3381 Vector3 grabforce = llmoveforce;
2670 grabforce = (grabforce / 10) * pa.Mass; 3382 grabforce = (grabforce / 10) * pa.Mass;
2671 pa.AddForce(grabforce, true); 3383 */
3384 // empirically convert distance diference to a impulse
3385 Vector3 grabforce = pos - AbsolutePosition;
3386 grabforce = grabforce * (pa.Mass/ 10.0f);
3387 pa.AddForce(grabforce, false);
2672 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 3388 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2673 } 3389 }
2674 } 3390 }
@@ -2882,6 +3598,8 @@ namespace OpenSim.Region.Framework.Scenes
2882 /// <param name="SetVolumeDetect"></param> 3598 /// <param name="SetVolumeDetect"></param>
2883 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) 3599 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect)
2884 { 3600 {
3601 HasGroupChanged = true;
3602
2885 SceneObjectPart selectionPart = GetPart(localID); 3603 SceneObjectPart selectionPart = GetPart(localID);
2886 3604
2887 if (Scene != null) 3605 if (Scene != null)
@@ -2907,8 +3625,12 @@ namespace OpenSim.Region.Framework.Scenes
2907 { 3625 {
2908 SceneObjectPart[] parts = m_parts.GetArray(); 3626 SceneObjectPart[] parts = m_parts.GetArray();
2909 3627
2910 if (Scene != null) 3628 if (Scene != null && UsePhysics)
2911 { 3629 {
3630 int maxprims = m_scene.m_linksetPhysCapacity;
3631 bool checkShape = (maxprims > 0 &&
3632 parts.Length > maxprims);
3633
2912 for (int i = 0; i < parts.Length; i++) 3634 for (int i = 0; i < parts.Length; i++)
2913 { 3635 {
2914 SceneObjectPart part = parts[i]; 3636 SceneObjectPart part = parts[i];
@@ -2919,11 +3641,34 @@ namespace OpenSim.Region.Framework.Scenes
2919 UsePhysics = false; // Reset physics 3641 UsePhysics = false; // Reset physics
2920 break; 3642 break;
2921 } 3643 }
3644
3645 if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3646 {
3647 if (--maxprims < 0)
3648 {
3649 UsePhysics = false;
3650 break;
3651 }
3652 }
2922 } 3653 }
2923 } 3654 }
2924 3655
2925 for (int i = 0; i < parts.Length; i++) 3656 if (parts.Length > 1)
2926 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3657 {
3658 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3659
3660 for (int i = 0; i < parts.Length; i++)
3661 {
3662
3663 if (parts[i].UUID != m_rootPart.UUID)
3664 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3665 }
3666
3667 if (m_rootPart.PhysActor != null)
3668 m_rootPart.PhysActor.Building = false;
3669 }
3670 else
3671 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
2927 } 3672 }
2928 } 3673 }
2929 3674
@@ -2936,6 +3681,17 @@ namespace OpenSim.Region.Framework.Scenes
2936 } 3681 }
2937 } 3682 }
2938 3683
3684
3685
3686 /// <summary>
3687 /// Gets the number of parts
3688 /// </summary>
3689 /// <returns></returns>
3690 public int GetPartCount()
3691 {
3692 return Parts.Count();
3693 }
3694
2939 /// <summary> 3695 /// <summary>
2940 /// Update the texture entry for this part 3696 /// Update the texture entry for this part
2941 /// </summary> 3697 /// </summary>
@@ -2980,7 +3736,23 @@ namespace OpenSim.Region.Framework.Scenes
2980 { 3736 {
2981 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); 3737 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2982 3738
2983 AdjustChildPrimPermissions(Scene.Permissions.IsGod(AgentID)); 3739 bool god = Scene.Permissions.IsGod(AgentID);
3740
3741 if (field == 1 && god)
3742 {
3743 ForEachPart(part =>
3744 {
3745 part.BaseMask = RootPart.BaseMask;
3746 });
3747 }
3748
3749 AdjustChildPrimPermissions(false);
3750
3751 if (field == 1 && god) // Base mask was set. Update all child part inventories
3752 {
3753 foreach (SceneObjectPart part in Parts)
3754 part.Inventory.ApplyGodPermissions(RootPart.BaseMask);
3755 }
2984 3756
2985 HasGroupChanged = true; 3757 HasGroupChanged = true;
2986 3758
@@ -3025,163 +3797,101 @@ namespace OpenSim.Region.Framework.Scenes
3025// m_log.DebugFormat( 3797// m_log.DebugFormat(
3026// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 3798// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
3027 3799
3800 if (Scene == null)
3801 return;
3802
3028 PhysicsActor pa = m_rootPart.PhysActor; 3803 PhysicsActor pa = m_rootPart.PhysActor;
3029 3804
3030 RootPart.StoreUndoState(true); 3805 float minsize = Scene.m_minNonphys;
3806 float maxsize = Scene.m_maxNonphys;
3031 3807
3032 if (Scene != null) 3808 if (pa != null && pa.IsPhysical)
3033 { 3809 {
3034 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); 3810 minsize = Scene.m_minPhys;
3035 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); 3811 maxsize = Scene.m_maxPhys;
3036 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
3037
3038 if (pa != null && pa.IsPhysical)
3039 {
3040 scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
3041 scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
3042 scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
3043 }
3044 } 3812 }
3045 3813
3814 scale.X = Util.Clamp(scale.X, minsize, maxsize);
3815 scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
3816 scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
3817
3818 // requested scaling factors
3046 float x = (scale.X / RootPart.Scale.X); 3819 float x = (scale.X / RootPart.Scale.X);
3047 float y = (scale.Y / RootPart.Scale.Y); 3820 float y = (scale.Y / RootPart.Scale.Y);
3048 float z = (scale.Z / RootPart.Scale.Z); 3821 float z = (scale.Z / RootPart.Scale.Z);
3049 3822
3050 SceneObjectPart[] parts = m_parts.GetArray(); 3823 SceneObjectPart[] parts = m_parts.GetArray();
3051 3824
3052 if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f)) 3825 // fix scaling factors so parts don't violate dimensions
3826 for(int i = 0;i < parts.Length;i++)
3053 { 3827 {
3054 for (int i = 0; i < parts.Length; i++) 3828 SceneObjectPart obPart = parts[i];
3829 if(obPart.UUID != m_rootPart.UUID)
3055 { 3830 {
3056 SceneObjectPart obPart = parts[i]; 3831 Vector3 oldSize = new Vector3(obPart.Scale);
3057 if (obPart.UUID != m_rootPart.UUID)
3058 {
3059// obPart.IgnoreUndoUpdate = true;
3060 Vector3 oldSize = new Vector3(obPart.Scale);
3061
3062 float f = 1.0f;
3063 float a = 1.0f;
3064
3065 if (pa != null && pa.IsPhysical)
3066 {
3067 if (oldSize.X * x > Scene.m_maxPhys)
3068 {
3069 f = m_scene.m_maxPhys / oldSize.X;
3070 a = f / x;
3071 x *= a;
3072 y *= a;
3073 z *= a;
3074 }
3075 else if (oldSize.X * x < Scene.m_minPhys)
3076 {
3077 f = m_scene.m_minPhys / oldSize.X;
3078 a = f / x;
3079 x *= a;
3080 y *= a;
3081 z *= a;
3082 }
3083
3084 if (oldSize.Y * y > Scene.m_maxPhys)
3085 {
3086 f = m_scene.m_maxPhys / oldSize.Y;
3087 a = f / y;
3088 x *= a;
3089 y *= a;
3090 z *= a;
3091 }
3092 else if (oldSize.Y * y < Scene.m_minPhys)
3093 {
3094 f = m_scene.m_minPhys / oldSize.Y;
3095 a = f / y;
3096 x *= a;
3097 y *= a;
3098 z *= a;
3099 }
3100 3832
3101 if (oldSize.Z * z > Scene.m_maxPhys) 3833 float f = 1.0f;
3102 { 3834 float a = 1.0f;
3103 f = m_scene.m_maxPhys / oldSize.Z;
3104 a = f / z;
3105 x *= a;
3106 y *= a;
3107 z *= a;
3108 }
3109 else if (oldSize.Z * z < Scene.m_minPhys)
3110 {
3111 f = m_scene.m_minPhys / oldSize.Z;
3112 a = f / z;
3113 x *= a;
3114 y *= a;
3115 z *= a;
3116 }
3117 }
3118 else
3119 {
3120 if (oldSize.X * x > Scene.m_maxNonphys)
3121 {
3122 f = m_scene.m_maxNonphys / oldSize.X;
3123 a = f / x;
3124 x *= a;
3125 y *= a;
3126 z *= a;
3127 }
3128 else if (oldSize.X * x < Scene.m_minNonphys)
3129 {
3130 f = m_scene.m_minNonphys / oldSize.X;
3131 a = f / x;
3132 x *= a;
3133 y *= a;
3134 z *= a;
3135 }
3136 3835
3137 if (oldSize.Y * y > Scene.m_maxNonphys) 3836 if(oldSize.X * x > maxsize)
3138 { 3837 {
3139 f = m_scene.m_maxNonphys / oldSize.Y; 3838 f = maxsize / oldSize.X;
3140 a = f / y; 3839 a = f / x;
3141 x *= a; 3840 x *= a;
3142 y *= a; 3841 y *= a;
3143 z *= a; 3842 z *= a;
3144 } 3843 }
3145 else if (oldSize.Y * y < Scene.m_minNonphys) 3844 else if(oldSize.X * x < minsize)
3146 { 3845 {
3147 f = m_scene.m_minNonphys / oldSize.Y; 3846 f = minsize / oldSize.X;
3148 a = f / y; 3847 a = f / x;
3149 x *= a; 3848 x *= a;
3150 y *= a; 3849 y *= a;
3151 z *= a; 3850 z *= a;
3152 } 3851 }
3153 3852
3154 if (oldSize.Z * z > Scene.m_maxNonphys) 3853 if(oldSize.Y * y > maxsize)
3155 { 3854 {
3156 f = m_scene.m_maxNonphys / oldSize.Z; 3855 f = maxsize / oldSize.Y;
3157 a = f / z; 3856 a = f / y;
3158 x *= a; 3857 x *= a;
3159 y *= a; 3858 y *= a;
3160 z *= a; 3859 z *= a;
3161 } 3860 }
3162 else if (oldSize.Z * z < Scene.m_minNonphys) 3861 else if(oldSize.Y * y < minsize)
3163 { 3862 {
3164 f = m_scene.m_minNonphys / oldSize.Z; 3863 f = minsize / oldSize.Y;
3165 a = f / z; 3864 a = f / y;
3166 x *= a; 3865 x *= a;
3167 y *= a; 3866 y *= a;
3168 z *= a; 3867 z *= a;
3169 } 3868 }
3170 }
3171 3869
3172// obPart.IgnoreUndoUpdate = false; 3870 if(oldSize.Z * z > maxsize)
3871 {
3872 f = maxsize / oldSize.Z;
3873 a = f / z;
3874 x *= a;
3875 y *= a;
3876 z *= a;
3877 }
3878 else if(oldSize.Z * z < minsize)
3879 {
3880 f = minsize / oldSize.Z;
3881 a = f / z;
3882 x *= a;
3883 y *= a;
3884 z *= a;
3173 } 3885 }
3174 } 3886 }
3175 } 3887 }
3176 3888
3177 Vector3 prevScale = RootPart.Scale; 3889 Vector3 rootScale = RootPart.Scale;
3178 prevScale.X *= x; 3890 rootScale.X *= x;
3179 prevScale.Y *= y; 3891 rootScale.Y *= y;
3180 prevScale.Z *= z; 3892 rootScale.Z *= z;
3181 3893
3182// RootPart.IgnoreUndoUpdate = true; 3894 RootPart.Scale = rootScale;
3183 RootPart.Resize(prevScale);
3184// RootPart.IgnoreUndoUpdate = false;
3185 3895
3186 for (int i = 0; i < parts.Length; i++) 3896 for (int i = 0; i < parts.Length; i++)
3187 { 3897 {
@@ -3189,8 +3899,6 @@ namespace OpenSim.Region.Framework.Scenes
3189 3899
3190 if (obPart.UUID != m_rootPart.UUID) 3900 if (obPart.UUID != m_rootPart.UUID)
3191 { 3901 {
3192 obPart.IgnoreUndoUpdate = true;
3193
3194 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3902 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
3195 currentpos.X *= x; 3903 currentpos.X *= x;
3196 currentpos.Y *= y; 3904 currentpos.Y *= y;
@@ -3201,18 +3909,14 @@ namespace OpenSim.Region.Framework.Scenes
3201 newSize.Y *= y; 3909 newSize.Y *= y;
3202 newSize.Z *= z; 3910 newSize.Z *= z;
3203 3911
3204 obPart.Resize(newSize); 3912 obPart.Scale = newSize;
3205 obPart.UpdateOffSet(currentpos); 3913 obPart.UpdateOffSet(currentpos);
3206
3207 obPart.IgnoreUndoUpdate = false;
3208 } 3914 }
3209 3915
3210// obPart.IgnoreUndoUpdate = false; 3916 HasGroupChanged = true;
3211// obPart.StoreUndoState(); 3917 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3918 ScheduleGroupForTerseUpdate();
3212 } 3919 }
3213
3214// m_log.DebugFormat(
3215// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
3216 } 3920 }
3217 3921
3218 #endregion 3922 #endregion
@@ -3225,14 +3929,6 @@ namespace OpenSim.Region.Framework.Scenes
3225 /// <param name="pos"></param> 3929 /// <param name="pos"></param>
3226 public void UpdateGroupPosition(Vector3 pos) 3930 public void UpdateGroupPosition(Vector3 pos)
3227 { 3931 {
3228// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
3229
3230 RootPart.StoreUndoState(true);
3231
3232// SceneObjectPart[] parts = m_parts.GetArray();
3233// for (int i = 0; i < parts.Length; i++)
3234// parts[i].StoreUndoState();
3235
3236 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3932 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
3237 { 3933 {
3238 if (IsAttachment) 3934 if (IsAttachment)
@@ -3265,21 +3961,17 @@ namespace OpenSim.Region.Framework.Scenes
3265 /// </summary> 3961 /// </summary>
3266 /// <param name="pos"></param> 3962 /// <param name="pos"></param>
3267 /// <param name="localID"></param> 3963 /// <param name="localID"></param>
3964 ///
3965
3268 public void UpdateSinglePosition(Vector3 pos, uint localID) 3966 public void UpdateSinglePosition(Vector3 pos, uint localID)
3269 { 3967 {
3270 SceneObjectPart part = GetPart(localID); 3968 SceneObjectPart part = GetPart(localID);
3271 3969
3272// SceneObjectPart[] parts = m_parts.GetArray();
3273// for (int i = 0; i < parts.Length; i++)
3274// parts[i].StoreUndoState();
3275
3276 if (part != null) 3970 if (part != null)
3277 { 3971 {
3278// m_log.DebugFormat( 3972// unlock parts position change
3279// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3973 if (m_rootPart.PhysActor != null)
3280 3974 m_rootPart.PhysActor.Building = true;
3281 part.StoreUndoState(false);
3282 part.IgnoreUndoUpdate = true;
3283 3975
3284 if (part.UUID == m_rootPart.UUID) 3976 if (part.UUID == m_rootPart.UUID)
3285 { 3977 {
@@ -3290,8 +3982,10 @@ namespace OpenSim.Region.Framework.Scenes
3290 part.UpdateOffSet(pos); 3982 part.UpdateOffSet(pos);
3291 } 3983 }
3292 3984
3985 if (m_rootPart.PhysActor != null)
3986 m_rootPart.PhysActor.Building = false;
3987
3293 HasGroupChanged = true; 3988 HasGroupChanged = true;
3294 part.IgnoreUndoUpdate = false;
3295 } 3989 }
3296 } 3990 }
3297 3991
@@ -3301,13 +3995,7 @@ namespace OpenSim.Region.Framework.Scenes
3301 /// <param name="newPos"></param> 3995 /// <param name="newPos"></param>
3302 public void UpdateRootPosition(Vector3 newPos) 3996 public void UpdateRootPosition(Vector3 newPos)
3303 { 3997 {
3304// m_log.DebugFormat( 3998 // needs to be called with phys building true
3305// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
3306
3307// SceneObjectPart[] parts = m_parts.GetArray();
3308// for (int i = 0; i < parts.Length; i++)
3309// parts[i].StoreUndoState();
3310
3311 Vector3 oldPos; 3999 Vector3 oldPos;
3312 4000
3313 if (IsAttachment) 4001 if (IsAttachment)
@@ -3328,12 +4016,19 @@ namespace OpenSim.Region.Framework.Scenes
3328 } 4016 }
3329 4017
3330 AbsolutePosition = newPos; 4018 AbsolutePosition = newPos;
3331 4019
3332 if (IsAttachment) 4020 if (IsAttachment)
3333 m_rootPart.AttachedPos = newPos; 4021 m_rootPart.AttachedPos = newPos;
3334 4022
3335 HasGroupChanged = true; 4023 HasGroupChanged = true;
3336 ScheduleGroupForTerseUpdate(); 4024 if (m_rootPart.Undoing)
4025 {
4026 ScheduleGroupForFullUpdate();
4027 }
4028 else
4029 {
4030 ScheduleGroupForTerseUpdate();
4031 }
3337 } 4032 }
3338 4033
3339 #endregion 4034 #endregion
@@ -3346,24 +4041,16 @@ namespace OpenSim.Region.Framework.Scenes
3346 /// <param name="rot"></param> 4041 /// <param name="rot"></param>
3347 public void UpdateGroupRotationR(Quaternion rot) 4042 public void UpdateGroupRotationR(Quaternion rot)
3348 { 4043 {
3349// m_log.DebugFormat(
3350// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
3351
3352// SceneObjectPart[] parts = m_parts.GetArray();
3353// for (int i = 0; i < parts.Length; i++)
3354// parts[i].StoreUndoState();
3355
3356 m_rootPart.StoreUndoState(true);
3357
3358 m_rootPart.UpdateRotation(rot); 4044 m_rootPart.UpdateRotation(rot);
3359 4045
4046/* this is done by rootpart RotationOffset set called by UpdateRotation
3360 PhysicsActor actor = m_rootPart.PhysActor; 4047 PhysicsActor actor = m_rootPart.PhysActor;
3361 if (actor != null) 4048 if (actor != null)
3362 { 4049 {
3363 actor.Orientation = m_rootPart.RotationOffset; 4050 actor.Orientation = m_rootPart.RotationOffset;
3364 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 4051 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
3365 } 4052 }
3366 4053*/
3367 HasGroupChanged = true; 4054 HasGroupChanged = true;
3368 ScheduleGroupForTerseUpdate(); 4055 ScheduleGroupForTerseUpdate();
3369 } 4056 }
@@ -3375,16 +4062,6 @@ namespace OpenSim.Region.Framework.Scenes
3375 /// <param name="rot"></param> 4062 /// <param name="rot"></param>
3376 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 4063 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
3377 { 4064 {
3378// m_log.DebugFormat(
3379// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
3380
3381// SceneObjectPart[] parts = m_parts.GetArray();
3382// for (int i = 0; i < parts.Length; i++)
3383// parts[i].StoreUndoState();
3384
3385 RootPart.StoreUndoState(true);
3386 RootPart.IgnoreUndoUpdate = true;
3387
3388 m_rootPart.UpdateRotation(rot); 4065 m_rootPart.UpdateRotation(rot);
3389 4066
3390 PhysicsActor actor = m_rootPart.PhysActor; 4067 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3403,8 +4080,6 @@ namespace OpenSim.Region.Framework.Scenes
3403 4080
3404 HasGroupChanged = true; 4081 HasGroupChanged = true;
3405 ScheduleGroupForTerseUpdate(); 4082 ScheduleGroupForTerseUpdate();
3406
3407 RootPart.IgnoreUndoUpdate = false;
3408 } 4083 }
3409 4084
3410 /// <summary> 4085 /// <summary>
@@ -3417,13 +4092,11 @@ namespace OpenSim.Region.Framework.Scenes
3417 SceneObjectPart part = GetPart(localID); 4092 SceneObjectPart part = GetPart(localID);
3418 4093
3419 SceneObjectPart[] parts = m_parts.GetArray(); 4094 SceneObjectPart[] parts = m_parts.GetArray();
3420 for (int i = 0; i < parts.Length; i++)
3421 parts[i].StoreUndoState();
3422 4095
3423 if (part != null) 4096 if (part != null)
3424 { 4097 {
3425// m_log.DebugFormat( 4098 if (m_rootPart.PhysActor != null)
3426// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 4099 m_rootPart.PhysActor.Building = true;
3427 4100
3428 if (part.UUID == m_rootPart.UUID) 4101 if (part.UUID == m_rootPart.UUID)
3429 { 4102 {
@@ -3433,6 +4106,9 @@ namespace OpenSim.Region.Framework.Scenes
3433 { 4106 {
3434 part.UpdateRotation(rot); 4107 part.UpdateRotation(rot);
3435 } 4108 }
4109
4110 if (m_rootPart.PhysActor != null)
4111 m_rootPart.PhysActor.Building = false;
3436 } 4112 }
3437 } 4113 }
3438 4114
@@ -3446,12 +4122,8 @@ namespace OpenSim.Region.Framework.Scenes
3446 SceneObjectPart part = GetPart(localID); 4122 SceneObjectPart part = GetPart(localID);
3447 if (part != null) 4123 if (part != null)
3448 { 4124 {
3449// m_log.DebugFormat( 4125 if (m_rootPart.PhysActor != null)
3450// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 4126 m_rootPart.PhysActor.Building = true;
3451// part.Name, part.LocalId, rot);
3452
3453 part.StoreUndoState();
3454 part.IgnoreUndoUpdate = true;
3455 4127
3456 if (part.UUID == m_rootPart.UUID) 4128 if (part.UUID == m_rootPart.UUID)
3457 { 4129 {
@@ -3464,7 +4136,8 @@ namespace OpenSim.Region.Framework.Scenes
3464 part.OffsetPosition = pos; 4136 part.OffsetPosition = pos;
3465 } 4137 }
3466 4138
3467 part.IgnoreUndoUpdate = false; 4139 if (m_rootPart.PhysActor != null)
4140 m_rootPart.PhysActor.Building = false;
3468 } 4141 }
3469 } 4142 }
3470 4143
@@ -3474,15 +4147,12 @@ namespace OpenSim.Region.Framework.Scenes
3474 /// <param name="rot"></param> 4147 /// <param name="rot"></param>
3475 public void UpdateRootRotation(Quaternion rot) 4148 public void UpdateRootRotation(Quaternion rot)
3476 { 4149 {
3477// m_log.DebugFormat( 4150 // needs to be called with phys building true
3478// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
3479// Name, LocalId, rot);
3480
3481 Quaternion axRot = rot; 4151 Quaternion axRot = rot;
3482 Quaternion oldParentRot = m_rootPart.RotationOffset; 4152 Quaternion oldParentRot = m_rootPart.RotationOffset;
3483 4153
3484 m_rootPart.StoreUndoState(); 4154 //Don't use UpdateRotation because it schedules an update prematurely
3485 m_rootPart.UpdateRotation(rot); 4155 m_rootPart.RotationOffset = rot;
3486 4156
3487 PhysicsActor pa = m_rootPart.PhysActor; 4157 PhysicsActor pa = m_rootPart.PhysActor;
3488 4158
@@ -3498,64 +4168,203 @@ namespace OpenSim.Region.Framework.Scenes
3498 SceneObjectPart prim = parts[i]; 4168 SceneObjectPart prim = parts[i];
3499 if (prim.UUID != m_rootPart.UUID) 4169 if (prim.UUID != m_rootPart.UUID)
3500 { 4170 {
3501 prim.IgnoreUndoUpdate = true; 4171 Quaternion NewRot = oldParentRot * prim.RotationOffset;
4172 NewRot = Quaternion.Inverse(axRot) * NewRot;
4173 prim.RotationOffset = NewRot;
4174
3502 Vector3 axPos = prim.OffsetPosition; 4175 Vector3 axPos = prim.OffsetPosition;
4176
3503 axPos *= oldParentRot; 4177 axPos *= oldParentRot;
3504 axPos *= Quaternion.Inverse(axRot); 4178 axPos *= Quaternion.Inverse(axRot);
3505 prim.OffsetPosition = axPos; 4179 prim.OffsetPosition = axPos;
3506 Quaternion primsRot = prim.RotationOffset;
3507 Quaternion newRot = oldParentRot * primsRot;
3508 newRot = Quaternion.Inverse(axRot) * newRot;
3509 prim.RotationOffset = newRot;
3510 prim.ScheduleTerseUpdate();
3511 prim.IgnoreUndoUpdate = false;
3512 } 4180 }
3513 } 4181 }
3514 4182
3515// for (int i = 0; i < parts.Length; i++) 4183 HasGroupChanged = true;
3516// { 4184 ScheduleGroupForFullUpdate();
3517// SceneObjectPart childpart = parts[i]; 4185 }
3518// if (childpart != m_rootPart) 4186
3519// { 4187 private enum updatetype :int
3520//// childpart.IgnoreUndoUpdate = false; 4188 {
3521//// childpart.StoreUndoState(); 4189 none = 0,
3522// } 4190 partterse = 1,
3523// } 4191 partfull = 2,
4192 groupterse = 3,
4193 groupfull = 4
4194 }
3524 4195
3525 m_rootPart.ScheduleTerseUpdate(); 4196 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
4197 {
4198 // TODO this still as excessive *.Schedule*Update()s
3526 4199
3527// m_log.DebugFormat( 4200 if (part != null && part.ParentGroup != null)
3528// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 4201 {
3529// Name, LocalId, rot); 4202 ObjectChangeType change = data.change;
4203 bool togroup = ((change & ObjectChangeType.Group) != 0);
4204 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
4205
4206 SceneObjectGroup group = part.ParentGroup;
4207 PhysicsActor pha = group.RootPart.PhysActor;
4208
4209 updatetype updateType = updatetype.none;
4210
4211 if (togroup)
4212 {
4213 // related to group
4214 if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0)
4215 {
4216 if ((change & ObjectChangeType.Rotation) != 0)
4217 {
4218 group.RootPart.UpdateRotation(data.rotation);
4219 updateType = updatetype.none;
4220 }
4221 if ((change & ObjectChangeType.Position) != 0)
4222 {
4223 if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position))
4224 UpdateGroupPosition(data.position);
4225 updateType = updatetype.groupterse;
4226 }
4227 else
4228 // ugly rotation update of all parts
4229 {
4230 group.ResetChildPrimPhysicsPositions();
4231 }
4232
4233 }
4234 if ((change & ObjectChangeType.Scale) != 0)
4235 {
4236 if (pha != null)
4237 pha.Building = true;
4238
4239 group.GroupResize(data.scale);
4240 updateType = updatetype.none;
4241
4242 if (pha != null)
4243 pha.Building = false;
4244 }
4245 }
4246 else
4247 {
4248 // related to single prim in a link-set ( ie group)
4249 if (pha != null)
4250 pha.Building = true;
4251
4252 // root part is special
4253 // parts offset positions or rotations need to change also
4254
4255 if (part == group.RootPart)
4256 {
4257 if ((change & ObjectChangeType.Rotation) != 0)
4258 group.UpdateRootRotation(data.rotation);
4259 if ((change & ObjectChangeType.Position) != 0)
4260 group.UpdateRootPosition(data.position);
4261 if ((change & ObjectChangeType.Scale) != 0)
4262 part.Resize(data.scale);
4263 }
4264 else
4265 {
4266 if ((change & ObjectChangeType.Position) != 0)
4267 {
4268 part.OffsetPosition = data.position;
4269 updateType = updatetype.partterse;
4270 }
4271 if ((change & ObjectChangeType.Rotation) != 0)
4272 {
4273 part.UpdateRotation(data.rotation);
4274 updateType = updatetype.none;
4275 }
4276 if ((change & ObjectChangeType.Scale) != 0)
4277 {
4278 part.Resize(data.scale);
4279 updateType = updatetype.none;
4280 }
4281 }
4282
4283 if (pha != null)
4284 pha.Building = false;
4285 }
4286
4287 if (updateType != updatetype.none)
4288 {
4289 group.HasGroupChanged = true;
4290
4291 switch (updateType)
4292 {
4293 case updatetype.partterse:
4294 part.ScheduleTerseUpdate();
4295 break;
4296 case updatetype.partfull:
4297 part.ScheduleFullUpdate();
4298 break;
4299 case updatetype.groupterse:
4300 group.ScheduleGroupForTerseUpdate();
4301 break;
4302 case updatetype.groupfull:
4303 group.ScheduleGroupForFullUpdate();
4304 break;
4305 default:
4306 break;
4307 }
4308 }
4309 }
3530 } 4310 }
3531 4311
3532 #endregion 4312 #endregion
3533 4313
3534 internal void SetAxisRotation(int axis, int rotate10) 4314 internal void SetAxisRotation(int axis, int rotate10)
3535 { 4315 {
3536 bool setX = false; 4316 bool setX = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0);
3537 bool setY = false; 4317 bool setY = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0);
3538 bool setZ = false; 4318 bool setZ = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0);
3539 4319
3540 int xaxis = 2; 4320 if (setX || setY || setZ)
3541 int yaxis = 4; 4321 {
3542 int zaxis = 8; 4322 bool lockaxis = (rotate10 == 0); // zero means axis locked
3543 4323
3544 setX = ((axis & xaxis) != 0) ? true : false; 4324 byte locks = RootPart.RotationAxisLocks;
3545 setY = ((axis & yaxis) != 0) ? true : false;
3546 setZ = ((axis & zaxis) != 0) ? true : false;
3547 4325
3548 float setval = (rotate10 > 0) ? 1f : 0f; 4326 if (setX)
4327 {
4328 if(lockaxis)
4329 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_X;
4330 else
4331 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_X;
4332 }
4333
4334 if (setY)
4335 {
4336 if(lockaxis)
4337 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y;
4338 else
4339 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_Y;
4340 }
3549 4341
3550 if (setX) 4342 if (setZ)
3551 RootPart.RotationAxis.X = setval; 4343 {
3552 if (setY) 4344 if(lockaxis)
3553 RootPart.RotationAxis.Y = setval; 4345 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z;
3554 if (setZ) 4346 else
3555 RootPart.RotationAxis.Z = setval; 4347 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_Z;
4348 }
3556 4349
3557 if (setX || setY || setZ) 4350 RootPart.RotationAxisLocks = locks;
3558 RootPart.SetPhysicsAxisRotation(); 4351 RootPart.SetPhysicsAxisRotation();
4352 }
4353 }
4354
4355 public int GetAxisRotation(int axis)
4356 {
4357 byte rotAxislocks = RootPart.RotationAxisLocks;
4358
4359 // if multiple return the one with higher id
4360 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
4361 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) == 0 ? 1:0;
4362 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
4363 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) == 0 ? 1:0;
4364 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X)
4365 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) == 0 ? 1:0;
4366
4367 return 0;
3559 } 4368 }
3560 4369
3561 public int registerRotTargetWaypoint(Quaternion target, float tolerance) 4370 public int registerRotTargetWaypoint(Quaternion target, float tolerance)
@@ -3567,6 +4376,8 @@ namespace OpenSim.Region.Framework.Scenes
3567 waypoint.handle = handle; 4376 waypoint.handle = handle;
3568 lock (m_rotTargets) 4377 lock (m_rotTargets)
3569 { 4378 {
4379 if (m_rotTargets.Count >= 8)
4380 m_rotTargets.Remove(m_rotTargets.ElementAt(0).Key);
3570 m_rotTargets.Add(handle, waypoint); 4381 m_rotTargets.Add(handle, waypoint);
3571 } 4382 }
3572 m_scene.AddGroupTarget(this); 4383 m_scene.AddGroupTarget(this);
@@ -3592,6 +4403,8 @@ namespace OpenSim.Region.Framework.Scenes
3592 waypoint.handle = handle; 4403 waypoint.handle = handle;
3593 lock (m_targets) 4404 lock (m_targets)
3594 { 4405 {
4406 if (m_targets.Count >= 8)
4407 m_targets.Remove(m_targets.ElementAt(0).Key);
3595 m_targets.Add(handle, waypoint); 4408 m_targets.Add(handle, waypoint);
3596 } 4409 }
3597 m_scene.AddGroupTarget(this); 4410 m_scene.AddGroupTarget(this);
@@ -3625,10 +4438,11 @@ namespace OpenSim.Region.Framework.Scenes
3625 scriptPosTarget target = m_targets[idx]; 4438 scriptPosTarget target = m_targets[idx];
3626 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) 4439 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
3627 { 4440 {
4441 at_target = true;
4442
3628 // trigger at_target 4443 // trigger at_target
3629 if (m_scriptListens_atTarget) 4444 if (m_scriptListens_atTarget)
3630 { 4445 {
3631 at_target = true;
3632 scriptPosTarget att = new scriptPosTarget(); 4446 scriptPosTarget att = new scriptPosTarget();
3633 att.targetPos = target.targetPos; 4447 att.targetPos = target.targetPos;
3634 att.tolerance = target.tolerance; 4448 att.tolerance = target.tolerance;
@@ -3746,11 +4560,50 @@ namespace OpenSim.Region.Framework.Scenes
3746 } 4560 }
3747 } 4561 }
3748 } 4562 }
3749 4563
4564 public Vector3 GetGeometricCenter()
4565 {
4566 // this is not real geometric center but a average of positions relative to root prim acording to
4567 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
4568 // ignoring tortured prims details since sl also seems to ignore
4569 // so no real use in doing it on physics
4570
4571 Vector3 gc = Vector3.Zero;
4572
4573 int nparts = m_parts.Count;
4574 if (nparts <= 1)
4575 return gc;
4576
4577 SceneObjectPart[] parts = m_parts.GetArray();
4578 nparts = parts.Length; // just in case it changed
4579 if (nparts <= 1)
4580 return gc;
4581
4582 Quaternion parentRot = RootPart.RotationOffset;
4583 Vector3 pPos;
4584
4585 // average all parts positions
4586 for (int i = 0; i < nparts; i++)
4587 {
4588 // do it directly
4589 // gc += parts[i].GetWorldPosition();
4590 if (parts[i] != RootPart)
4591 {
4592 pPos = parts[i].OffsetPosition;
4593 gc += pPos;
4594 }
4595
4596 }
4597 gc /= nparts;
4598
4599 // relative to root:
4600// gc -= AbsolutePosition;
4601 return gc;
4602 }
4603
3750 public float GetMass() 4604 public float GetMass()
3751 { 4605 {
3752 float retmass = 0f; 4606 float retmass = 0f;
3753
3754 SceneObjectPart[] parts = m_parts.GetArray(); 4607 SceneObjectPart[] parts = m_parts.GetArray();
3755 for (int i = 0; i < parts.Length; i++) 4608 for (int i = 0; i < parts.Length; i++)
3756 retmass += parts[i].GetMass(); 4609 retmass += parts[i].GetMass();
@@ -3758,6 +4611,39 @@ namespace OpenSim.Region.Framework.Scenes
3758 return retmass; 4611 return retmass;
3759 } 4612 }
3760 4613
4614 // center of mass of full object
4615 public Vector3 GetCenterOfMass()
4616 {
4617 PhysicsActor pa = RootPart.PhysActor;
4618
4619 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
4620 {
4621 // physics knows better about center of mass of physical prims
4622 Vector3 tmp = pa.CenterOfMass;
4623 return tmp;
4624 }
4625
4626 Vector3 Ptot = Vector3.Zero;
4627 float totmass = 0f;
4628 float m;
4629
4630 SceneObjectPart[] parts = m_parts.GetArray();
4631 for (int i = 0; i < parts.Length; i++)
4632 {
4633 m = parts[i].GetMass();
4634 Ptot += parts[i].GetPartCenterOfMass() * m;
4635 totmass += m;
4636 }
4637
4638 if (totmass == 0)
4639 totmass = 0;
4640 else
4641 totmass = 1 / totmass;
4642 Ptot *= totmass;
4643
4644 return Ptot;
4645 }
4646
3761 /// <summary> 4647 /// <summary>
3762 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that 4648 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
3763 /// the physics engine can use it. 4649 /// the physics engine can use it.
@@ -3937,6 +4823,14 @@ namespace OpenSim.Region.Framework.Scenes
3937 FromItemID = uuid; 4823 FromItemID = uuid;
3938 } 4824 }
3939 4825
4826 public void ResetOwnerChangeFlag()
4827 {
4828 ForEachPart(delegate(SceneObjectPart part)
4829 {
4830 part.ResetOwnerChangeFlag();
4831 });
4832 }
4833
3940 #endregion 4834 #endregion
3941 } 4835 }
3942} 4836}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index d1c5f72..52f9b51 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -64,7 +64,8 @@ namespace OpenSim.Region.Framework.Scenes
64 TELEPORT = 512, 64 TELEPORT = 512,
65 REGION_RESTART = 1024, 65 REGION_RESTART = 1024,
66 MEDIA = 2048, 66 MEDIA = 2048,
67 ANIMATION = 16384 67 ANIMATION = 16384,
68 POSITION = 32768
68 } 69 }
69 70
70 // I don't really know where to put this except here. 71 // I don't really know where to put this except here.
@@ -123,7 +124,18 @@ namespace OpenSim.Region.Framework.Scenes
123 /// Denote all sides of the prim 124 /// Denote all sides of the prim
124 /// </value> 125 /// </value>
125 public const int ALL_SIDES = -1; 126 public const int ALL_SIDES = -1;
126 127
128 private const scriptEvents PhysicsNeededSubsEvents = (
129 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
130 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
131 );
132 private const scriptEvents PhyscicsPhantonSubsEvents = (
133 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
134 );
135 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
136 scriptEvents.collision_start | scriptEvents.collision_end
137 );
138
127 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 139 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
128 140
129 /// <summary> 141 /// <summary>
@@ -160,7 +172,7 @@ namespace OpenSim.Region.Framework.Scenes
160 /// </remarks> 172 /// </remarks>
161 public bool IsRoot 173 public bool IsRoot
162 { 174 {
163 get { return ParentGroup.RootPart == this; } 175 get { return Object.ReferenceEquals(ParentGroup.RootPart, this); }
164 } 176 }
165 177
166 /// <summary> 178 /// <summary>
@@ -233,11 +245,22 @@ namespace OpenSim.Region.Framework.Scenes
233 245
234 public uint TimeStampTerse; 246 public uint TimeStampTerse;
235 247
236 public int STATUS_ROTATE_X; 248 // The following two are to hold the attachment data
249 // while an object is inworld
250 [XmlIgnore]
251 public byte AttachPoint = 0;
252
253 [XmlIgnore]
254 public Quaternion AttachRotation = Quaternion.Identity;
237 255
238 public int STATUS_ROTATE_Y; 256 [XmlIgnore]
257 public int STATUS_ROTATE_X; // this should not be used
258
259 [XmlIgnore]
260 public int STATUS_ROTATE_Y; // this should not be used
239 261
240 public int STATUS_ROTATE_Z; 262 [XmlIgnore]
263 public int STATUS_ROTATE_Z; // this should not be used
241 264
242 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>(); 265 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>();
243 266
@@ -257,10 +280,12 @@ namespace OpenSim.Region.Framework.Scenes
257 280
258 public Vector3 AttachedPos; 281 public Vector3 AttachedPos;
259 282
260 public Vector3 RotationAxis = Vector3.One; 283 // rotation locks on local X,Y and or Z axis bit flags
284 // bits are as in llSetStatus defined in SceneObjectGroup.axisSelect enum
285 // but reversed logic: bit cleared means free to rotate
286 public byte RotationAxisLocks = 0;
261 287
262 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 288 public bool VolumeDetectActive;
263 // Certainly this must be a persistant setting finally
264 289
265 public bool IsWaitingForFirstSpinUpdatePacket; 290 public bool IsWaitingForFirstSpinUpdatePacket;
266 291
@@ -300,10 +325,10 @@ namespace OpenSim.Region.Framework.Scenes
300 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 325 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
301 private Vector3 m_sitTargetPosition; 326 private Vector3 m_sitTargetPosition;
302 private string m_sitAnimation = "SIT"; 327 private string m_sitAnimation = "SIT";
328 private bool m_occupied; // KF if any av is sitting on this prim
303 private string m_text = String.Empty; 329 private string m_text = String.Empty;
304 private string m_touchName = String.Empty; 330 private string m_touchName = String.Empty;
305 private readonly List<UndoState> m_undo = new List<UndoState>(5); 331 private UndoRedoState m_UndoRedo = null;
306 private readonly List<UndoState> m_redo = new List<UndoState>(5);
307 332
308 private bool m_passTouches = false; 333 private bool m_passTouches = false;
309 private bool m_passCollisions = false; 334 private bool m_passCollisions = false;
@@ -331,14 +356,20 @@ namespace OpenSim.Region.Framework.Scenes
331 protected Vector3 m_lastVelocity; 356 protected Vector3 m_lastVelocity;
332 protected Vector3 m_lastAcceleration; 357 protected Vector3 m_lastAcceleration;
333 protected Vector3 m_lastAngularVelocity; 358 protected Vector3 m_lastAngularVelocity;
334 protected int m_lastTerseSent; 359 protected int m_lastUpdateSentTime;
360 protected float m_buoyancy = 0.0f;
361 protected Vector3 m_force;
362 protected Vector3 m_torque;
335 363
336 protected byte m_physicsShapeType = (byte)PhysShapeType.prim; 364 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
337 protected float m_density = 1000.0f; // in kg/m^3 365 protected float m_density = 1000.0f; // in kg/m^3
338 protected float m_gravitymod = 1.0f; 366 protected float m_gravitymod = 1.0f;
339 protected float m_friction = 0.6f; // wood 367 protected float m_friction = 0.6f; // wood
340 protected float m_bounce = 0.5f; // wood 368 protected float m_bounce = 0.5f; // wood
341 369
370
371 protected bool m_isSelected = false;
372
342 /// <summary> 373 /// <summary>
343 /// Stores media texture data 374 /// Stores media texture data
344 /// </summary> 375 /// </summary>
@@ -350,15 +381,23 @@ namespace OpenSim.Region.Framework.Scenes
350 private Vector3 m_cameraAtOffset; 381 private Vector3 m_cameraAtOffset;
351 private bool m_forceMouselook; 382 private bool m_forceMouselook;
352 383
353 // TODO: Collision sound should have default. 384
385 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
386 private sbyte m_collisionSoundType;
354 private UUID m_collisionSound; 387 private UUID m_collisionSound;
355 private float m_collisionSoundVolume; 388 private float m_collisionSoundVolume;
356 389
390 private int LastColSoundSentTime;
391
392
393 private SOPVehicle m_vehicleParams = null;
394
357 public KeyframeMotion KeyframeMotion 395 public KeyframeMotion KeyframeMotion
358 { 396 {
359 get; set; 397 get; set;
360 } 398 }
361 399
400
362 #endregion Fields 401 #endregion Fields
363 402
364// ~SceneObjectPart() 403// ~SceneObjectPart()
@@ -388,6 +427,7 @@ namespace OpenSim.Region.Framework.Scenes
388 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 427 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
389 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 428 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
390 m_inventory = new SceneObjectPartInventory(this); 429 m_inventory = new SceneObjectPartInventory(this);
430 LastColSoundSentTime = Util.EnvironmentTickCount();
391 } 431 }
392 432
393 /// <summary> 433 /// <summary>
@@ -402,7 +442,7 @@ namespace OpenSim.Region.Framework.Scenes
402 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 442 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
403 Quaternion rotationOffset, Vector3 offsetPosition) : this() 443 Quaternion rotationOffset, Vector3 offsetPosition) : this()
404 { 444 {
405 m_name = "Primitive"; 445 m_name = "Object";
406 446
407 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 447 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
408 LastOwnerID = CreatorID = OwnerID = ownerID; 448 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -441,7 +481,7 @@ namespace OpenSim.Region.Framework.Scenes
441 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export); 481 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export);
442 private uint _groupMask = (uint)PermissionMask.None; 482 private uint _groupMask = (uint)PermissionMask.None;
443 private uint _everyoneMask = (uint)PermissionMask.None; 483 private uint _everyoneMask = (uint)PermissionMask.None;
444 private uint _nextOwnerMask = (uint)PermissionMask.All; 484 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
445 private PrimFlags _flags = PrimFlags.None; 485 private PrimFlags _flags = PrimFlags.None;
446 private DateTime m_expires; 486 private DateTime m_expires;
447 private DateTime m_rezzed; 487 private DateTime m_rezzed;
@@ -539,12 +579,16 @@ namespace OpenSim.Region.Framework.Scenes
539 } 579 }
540 580
541 /// <value> 581 /// <value>
542 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 582 /// Get the inventory list
543 /// </value> 583 /// </value>
544 public TaskInventoryDictionary TaskInventory 584 public TaskInventoryDictionary TaskInventory
545 { 585 {
546 get { return m_inventory.Items; } 586 get {
547 set { m_inventory.Items = value; } 587 return m_inventory.Items;
588 }
589 set {
590 m_inventory.Items = value;
591 }
548 } 592 }
549 593
550 /// <summary> 594 /// <summary>
@@ -594,20 +638,6 @@ namespace OpenSim.Region.Framework.Scenes
594 } 638 }
595 } 639 }
596 640
597 public byte Material
598 {
599 get { return (byte) m_material; }
600 set
601 {
602 m_material = (Material)value;
603
604 PhysicsActor pa = PhysActor;
605
606 if (pa != null)
607 pa.SetMaterial((int)value);
608 }
609 }
610
611 [XmlIgnore] 641 [XmlIgnore]
612 public bool PassTouches 642 public bool PassTouches
613 { 643 {
@@ -633,6 +663,19 @@ namespace OpenSim.Region.Framework.Scenes
633 } 663 }
634 } 664 }
635 665
666 public bool IsSelected
667 {
668 get { return m_isSelected; }
669 set
670 {
671 m_isSelected = value;
672 if (ParentGroup != null)
673 ParentGroup.PartSelectChanged(value);
674
675 }
676 }
677
678
636 public Dictionary<int, string> CollisionFilter 679 public Dictionary<int, string> CollisionFilter
637 { 680 {
638 get { return m_CollisionFilter; } 681 get { return m_CollisionFilter; }
@@ -707,14 +750,12 @@ namespace OpenSim.Region.Framework.Scenes
707 set { m_LoopSoundSlavePrims = value; } 750 set { m_LoopSoundSlavePrims = value; }
708 } 751 }
709 752
710
711 public Byte[] TextureAnimation 753 public Byte[] TextureAnimation
712 { 754 {
713 get { return m_TextureAnimation; } 755 get { return m_TextureAnimation; }
714 set { m_TextureAnimation = value; } 756 set { m_TextureAnimation = value; }
715 } 757 }
716 758
717
718 public Byte[] ParticleSystem 759 public Byte[] ParticleSystem
719 { 760 {
720 get { return m_particleSystem; } 761 get { return m_particleSystem; }
@@ -742,18 +783,28 @@ namespace OpenSim.Region.Framework.Scenes
742 set { m_damage = value; } 783 set { m_damage = value; }
743 } 784 }
744 785
786 public void setGroupPosition(Vector3 pos)
787 {
788 m_groupPosition = pos;
789 }
790
745 /// <summary> 791 /// <summary>
746 /// The position of the entire group that this prim belongs to. 792 /// The position of the entire group that this prim belongs to.
747 /// </summary> 793 /// </summary>
794 ///
795
748 public Vector3 GroupPosition 796 public Vector3 GroupPosition
749 { 797 {
750 get 798 get
751 { 799 {
752 // If this is a linkset, we don't want the physics engine mucking up our group position here. 800 // If this is a linkset, we don't want the physics engine mucking up our group position here.
753 PhysicsActor actor = PhysActor; 801 PhysicsActor actor = PhysActor;
754 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 802 if (ParentID == 0)
755 if (actor != null && ParentID == 0) 803 {
756 m_groupPosition = actor.Position; 804 if (actor != null)
805 m_groupPosition = actor.Position;
806 return m_groupPosition;
807 }
757 808
758 // If I'm an attachment, my position is reported as the position of who I'm attached to 809 // If I'm an attachment, my position is reported as the position of who I'm attached to
759 if (ParentGroup.IsAttachment) 810 if (ParentGroup.IsAttachment)
@@ -763,21 +814,23 @@ namespace OpenSim.Region.Framework.Scenes
763 return sp.AbsolutePosition; 814 return sp.AbsolutePosition;
764 } 815 }
765 816
817 // use root prim's group position. Physics may have updated it
818 if (ParentGroup.RootPart != this)
819 m_groupPosition = ParentGroup.RootPart.GroupPosition;
766 return m_groupPosition; 820 return m_groupPosition;
767 } 821 }
768 set 822 set
769 { 823 {
770 m_groupPosition = value; 824 m_groupPosition = value;
771
772 PhysicsActor actor = PhysActor; 825 PhysicsActor actor = PhysActor;
773 if (actor != null) 826 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
774 { 827 {
775 try 828 try
776 { 829 {
777 // Root prim actually goes at Position 830 // Root prim actually goes at Position
778 if (ParentID == 0) 831 if (ParentID == 0)
779 { 832 {
780 actor.Position = value; 833 actor.Position = value;
781 } 834 }
782 else 835 else
783 { 836 {
@@ -798,12 +851,17 @@ namespace OpenSim.Region.Framework.Scenes
798 } 851 }
799 } 852 }
800 853
854 public void setOffsetPosition(Vector3 pos)
855 {
856 m_offsetPosition = pos;
857 }
858
801 public Vector3 OffsetPosition 859 public Vector3 OffsetPosition
802 { 860 {
803 get { return m_offsetPosition; } 861 get { return m_offsetPosition; }
804 set 862 set
805 { 863 {
806// StoreUndoState(); 864 Vector3 oldpos = m_offsetPosition;
807 m_offsetPosition = value; 865 m_offsetPosition = value;
808 866
809 if (ParentGroup != null && !ParentGroup.IsDeleted) 867 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -815,10 +873,26 @@ namespace OpenSim.Region.Framework.Scenes
815 actor.Orientation = GetWorldRotation(); 873 actor.Orientation = GetWorldRotation();
816 874
817 // Tell the physics engines that this prim changed. 875 // Tell the physics engines that this prim changed.
818 if (ParentGroup.Scene != null) 876 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
819 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 877 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
820 } 878 }
879
880 if (!m_parentGroup.m_dupeInProgress)
881 {
882 List<ScenePresence> avs = ParentGroup.GetSittingAvatars();
883 foreach (ScenePresence av in avs)
884 {
885 if (av.ParentID == m_localId)
886 {
887 Vector3 offset = (m_offsetPosition - oldpos);
888 av.AbsolutePosition += offset;
889// av.SendAvatarDataToAllAgents();
890 av.SendTerseUpdateToAllClients();
891 }
892 }
893 }
821 } 894 }
895 TriggerScriptChangedEvent(Changed.POSITION);
822 } 896 }
823 } 897 }
824 898
@@ -840,6 +914,11 @@ namespace OpenSim.Region.Framework.Scenes
840 } 914 }
841 } 915 }
842 916
917 public void setRotationOffset(Quaternion q)
918 {
919 m_rotationOffset = q;
920 }
921
843 public Quaternion RotationOffset 922 public Quaternion RotationOffset
844 { 923 {
845 get 924 get
@@ -869,7 +948,7 @@ namespace OpenSim.Region.Framework.Scenes
869 948
870 set 949 set
871 { 950 {
872 StoreUndoState(); 951// StoreUndoState();
873 m_rotationOffset = value; 952 m_rotationOffset = value;
874 953
875 PhysicsActor actor = PhysActor; 954 PhysicsActor actor = PhysActor;
@@ -960,7 +1039,7 @@ namespace OpenSim.Region.Framework.Scenes
960 get 1039 get
961 { 1040 {
962 PhysicsActor actor = PhysActor; 1041 PhysicsActor actor = PhysActor;
963 if ((actor != null) && actor.IsPhysical) 1042 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
964 { 1043 {
965 m_angularVelocity = actor.RotationalVelocity; 1044 m_angularVelocity = actor.RotationalVelocity;
966 } 1045 }
@@ -974,15 +1053,26 @@ namespace OpenSim.Region.Framework.Scenes
974 m_angularVelocity = value; 1053 m_angularVelocity = value;
975 1054
976 PhysicsActor actor = PhysActor; 1055 PhysicsActor actor = PhysActor;
977 if ((actor != null) && actor.IsPhysical) 1056 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this && VehicleType == (int)Vehicle.TYPE_NONE)
1057 {
978 actor.RotationalVelocity = m_angularVelocity; 1058 actor.RotationalVelocity = m_angularVelocity;
1059 }
979 } 1060 }
980 } 1061 }
981 1062
982 /// <summary></summary> 1063 /// <summary></summary>
983 public Vector3 Acceleration 1064 public Vector3 Acceleration
984 { 1065 {
985 get { return m_acceleration; } 1066 get
1067 {
1068 PhysicsActor actor = PhysActor;
1069 if (actor != null)
1070 {
1071 m_acceleration = actor.Acceleration;
1072 }
1073 return m_acceleration;
1074 }
1075
986 set 1076 set
987 { 1077 {
988 if (Util.IsNanOrInfinity(value)) 1078 if (Util.IsNanOrInfinity(value))
@@ -1056,7 +1146,10 @@ namespace OpenSim.Region.Framework.Scenes
1056 public PrimitiveBaseShape Shape 1146 public PrimitiveBaseShape Shape
1057 { 1147 {
1058 get { return m_shape; } 1148 get { return m_shape; }
1059 set { m_shape = value;} 1149 set
1150 {
1151 m_shape = value;
1152 }
1060 } 1153 }
1061 1154
1062 /// <summary> 1155 /// <summary>
@@ -1069,7 +1162,6 @@ namespace OpenSim.Region.Framework.Scenes
1069 { 1162 {
1070 if (m_shape != null) 1163 if (m_shape != null)
1071 { 1164 {
1072 StoreUndoState();
1073 1165
1074 m_shape.Scale = value; 1166 m_shape.Scale = value;
1075 1167
@@ -1137,10 +1229,7 @@ namespace OpenSim.Region.Framework.Scenes
1137 { 1229 {
1138 get 1230 get
1139 { 1231 {
1140 if (ParentGroup.IsAttachment) 1232 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1141 return GroupPosition;
1142
1143 return m_offsetPosition + m_groupPosition;
1144 } 1233 }
1145 } 1234 }
1146 1235
@@ -1309,6 +1398,13 @@ namespace OpenSim.Region.Framework.Scenes
1309 _flags = value; 1398 _flags = value;
1310 } 1399 }
1311 } 1400 }
1401
1402 [XmlIgnore]
1403 public bool IsOccupied // KF If an av is sittingon this prim
1404 {
1405 get { return m_occupied; }
1406 set { m_occupied = value; }
1407 }
1312 1408
1313 /// <summary> 1409 /// <summary>
1314 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero 1410 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
@@ -1359,12 +1455,41 @@ namespace OpenSim.Region.Framework.Scenes
1359 set { m_sitAnimation = value; } 1455 set { m_sitAnimation = value; }
1360 } 1456 }
1361 1457
1458 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1459
1460 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1461 // runtime thing.. do not persist
1462 [XmlIgnore]
1463 public sbyte CollisionSoundType
1464 {
1465 get
1466 {
1467 return m_collisionSoundType;
1468 }
1469 set
1470 {
1471 m_collisionSoundType = value;
1472 if (value == -1)
1473 m_collisionSound = invalidCollisionSoundUUID;
1474 else if (value == 0)
1475 m_collisionSound = UUID.Zero;
1476 }
1477 }
1478
1362 public UUID CollisionSound 1479 public UUID CollisionSound
1363 { 1480 {
1364 get { return m_collisionSound; } 1481 get { return m_collisionSound; }
1365 set 1482 set
1366 { 1483 {
1367 m_collisionSound = value; 1484 m_collisionSound = value;
1485
1486 if (value == invalidCollisionSoundUUID)
1487 m_collisionSoundType = -1;
1488 else if (value == UUID.Zero)
1489 m_collisionSoundType = 0;
1490 else
1491 m_collisionSoundType = 1;
1492
1368 aggregateScriptEvents(); 1493 aggregateScriptEvents();
1369 } 1494 }
1370 } 1495 }
@@ -1375,6 +1500,125 @@ namespace OpenSim.Region.Framework.Scenes
1375 set { m_collisionSoundVolume = value; } 1500 set { m_collisionSoundVolume = value; }
1376 } 1501 }
1377 1502
1503 public float Buoyancy
1504 {
1505 get
1506 {
1507 if (ParentGroup.RootPart == this)
1508 return m_buoyancy;
1509
1510 return ParentGroup.RootPart.Buoyancy;
1511 }
1512 set
1513 {
1514 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1515 {
1516 ParentGroup.RootPart.Buoyancy = value;
1517 return;
1518 }
1519 m_buoyancy = value;
1520 if (PhysActor != null)
1521 PhysActor.Buoyancy = value;
1522 }
1523 }
1524
1525 public Vector3 Force
1526 {
1527 get
1528 {
1529 if (ParentGroup.RootPart == this)
1530 return m_force;
1531
1532 return ParentGroup.RootPart.Force;
1533 }
1534
1535 set
1536 {
1537 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1538 {
1539 ParentGroup.RootPart.Force = value;
1540 return;
1541 }
1542 m_force = value;
1543 if (PhysActor != null)
1544 PhysActor.Force = value;
1545 }
1546 }
1547
1548 public Vector3 Torque
1549 {
1550 get
1551 {
1552 if (ParentGroup.RootPart == this)
1553 return m_torque;
1554
1555 return ParentGroup.RootPart.Torque;
1556 }
1557
1558 set
1559 {
1560 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1561 {
1562 ParentGroup.RootPart.Torque = value;
1563 return;
1564 }
1565 m_torque = value;
1566 if (PhysActor != null)
1567 PhysActor.Torque = value;
1568 }
1569 }
1570
1571 public byte Material
1572 {
1573 get { return (byte)m_material; }
1574 set
1575 {
1576 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1577 {
1578 bool update = false;
1579
1580 if (m_material != (Material)value)
1581 {
1582 update = true;
1583 m_material = (Material)value;
1584 }
1585
1586 if (m_friction != SOPMaterialData.friction(m_material))
1587 {
1588 update = true;
1589 m_friction = SOPMaterialData.friction(m_material);
1590 }
1591
1592 if (m_bounce != SOPMaterialData.bounce(m_material))
1593 {
1594 update = true;
1595 m_bounce = SOPMaterialData.bounce(m_material);
1596 }
1597
1598 if (update)
1599 {
1600 if (PhysActor != null)
1601 {
1602 PhysActor.SetMaterial((int)value);
1603 }
1604 if(ParentGroup != null)
1605 ParentGroup.HasGroupChanged = true;
1606 ScheduleFullUpdateIfNone();
1607 UpdatePhysRequired = true;
1608 }
1609 }
1610 }
1611 }
1612
1613 // not a propriety to move to methods place later
1614 private bool HasMesh()
1615 {
1616 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1617 return true;
1618 return false;
1619 }
1620
1621 // not a propriety to move to methods place later
1378 public byte DefaultPhysicsShapeType() 1622 public byte DefaultPhysicsShapeType()
1379 { 1623 {
1380 byte type; 1624 byte type;
@@ -1387,6 +1631,65 @@ namespace OpenSim.Region.Framework.Scenes
1387 return type; 1631 return type;
1388 } 1632 }
1389 1633
1634 [XmlIgnore]
1635 public bool UsesComplexCost
1636 {
1637 get
1638 {
1639 byte pst = PhysicsShapeType;
1640 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1641 return true;
1642 return false;
1643 }
1644 }
1645
1646 [XmlIgnore]
1647 public float PhysicsCost
1648 {
1649 get
1650 {
1651 if(PhysicsShapeType == (byte)PhysShapeType.none)
1652 return 0;
1653
1654 float cost = 0.1f;
1655 if (PhysActor != null)
1656 cost = PhysActor.PhysicsCost;
1657 else
1658 cost = 0.1f;
1659
1660 if ((Flags & PrimFlags.Physics) != 0)
1661 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1662 return cost;
1663 }
1664 }
1665
1666 [XmlIgnore]
1667 public float StreamingCost
1668 {
1669 get
1670 {
1671 float cost;
1672 if (PhysActor != null)
1673 cost = PhysActor.StreamCost;
1674 else
1675 cost = 1.0f;
1676 return 1.0f;
1677 }
1678 }
1679
1680 [XmlIgnore]
1681 public float SimulationCost
1682 {
1683 get
1684 {
1685 // ignoring scripts. Don't like considering them for this
1686 if((Flags & PrimFlags.Physics) != 0)
1687 return 1.0f;
1688
1689 return 0.5f;
1690 }
1691 }
1692
1390 public byte PhysicsShapeType 1693 public byte PhysicsShapeType
1391 { 1694 {
1392 get { return m_physicsShapeType; } 1695 get { return m_physicsShapeType; }
@@ -1420,11 +1723,14 @@ namespace OpenSim.Region.Framework.Scenes
1420 } 1723 }
1421 else if (PhysActor == null) 1724 else if (PhysActor == null)
1422 { 1725 {
1423 ApplyPhysics((uint)Flags, VolumeDetectActive); 1726 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1727 UpdatePhysicsSubscribedEvents();
1424 } 1728 }
1425 else 1729 else
1426 { 1730 {
1427 PhysActor.PhysicsShapeType = m_physicsShapeType; 1731 PhysActor.PhysicsShapeType = m_physicsShapeType;
1732// if (Shape.SculptEntry)
1733// CheckSculptAndLoad();
1428 } 1734 }
1429 1735
1430 if (ParentGroup != null) 1736 if (ParentGroup != null)
@@ -1526,6 +1832,7 @@ namespace OpenSim.Region.Framework.Scenes
1526 } 1832 }
1527 } 1833 }
1528 1834
1835
1529 #endregion Public Properties with only Get 1836 #endregion Public Properties with only Get
1530 1837
1531 private uint ApplyMask(uint val, bool set, uint mask) 1838 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1636,8 +1943,8 @@ namespace OpenSim.Region.Framework.Scenes
1636 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); 1943 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
1637 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); 1944 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
1638 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); 1945 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
1946
1639 } 1947 }
1640
1641 m_TextureAnimation = data; 1948 m_TextureAnimation = data;
1642 } 1949 }
1643 1950
@@ -1680,6 +1987,61 @@ namespace OpenSim.Region.Framework.Scenes
1680 } 1987 }
1681 } 1988 }
1682 1989
1990 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
1991 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
1992 {
1993 if (ParentGroup == null || ParentGroup.IsDeleted)
1994 return;
1995
1996 if (ParentGroup.IsAttachment)
1997 return; // don't work on attachments (for now ??)
1998
1999 SceneObjectPart root = ParentGroup.RootPart;
2000
2001 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2002 return;
2003
2004 PhysicsActor pa = root.PhysActor;
2005
2006 if (pa == null || !pa.IsPhysical)
2007 return;
2008
2009 if (localGlobalTF)
2010 {
2011 pVel = pVel * GetWorldRotation();
2012 }
2013
2014 ParentGroup.Velocity = pVel;
2015 }
2016
2017 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
2018 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
2019 {
2020 if (ParentGroup == null || ParentGroup.IsDeleted)
2021 return;
2022
2023 if (ParentGroup.IsAttachment)
2024 return; // don't work on attachments (for now ??)
2025
2026 SceneObjectPart root = ParentGroup.RootPart;
2027
2028 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2029 return;
2030
2031 PhysicsActor pa = root.PhysActor;
2032
2033 if (pa == null || !pa.IsPhysical)
2034 return;
2035
2036 if (localGlobalTF)
2037 {
2038 pAngVel = pAngVel * GetWorldRotation();
2039 }
2040
2041 root.AngularVelocity = pAngVel;
2042 }
2043
2044
1683 /// <summary> 2045 /// <summary>
1684 /// hook to the physics scene to apply angular impulse 2046 /// hook to the physics scene to apply angular impulse
1685 /// This is sent up to the group, which then finds the root prim 2047 /// This is sent up to the group, which then finds the root prim
@@ -1700,7 +2062,7 @@ namespace OpenSim.Region.Framework.Scenes
1700 impulse = newimpulse; 2062 impulse = newimpulse;
1701 } 2063 }
1702 2064
1703 ParentGroup.applyAngularImpulse(impulse); 2065 ParentGroup.ApplyAngularImpulse(impulse);
1704 } 2066 }
1705 2067
1706 /// <summary> 2068 /// <summary>
@@ -1710,20 +2072,24 @@ namespace OpenSim.Region.Framework.Scenes
1710 /// </summary> 2072 /// </summary>
1711 /// <param name="impulsei">Vector force</param> 2073 /// <param name="impulsei">Vector force</param>
1712 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 2074 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1713 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 2075
2076 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
2077 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1714 { 2078 {
1715 Vector3 impulse = impulsei; 2079 Vector3 torque = torquei;
1716 2080
1717 if (localGlobalTF) 2081 if (localGlobalTF)
1718 { 2082 {
2083/*
1719 Quaternion grot = GetWorldRotation(); 2084 Quaternion grot = GetWorldRotation();
1720 Quaternion AXgrot = grot; 2085 Quaternion AXgrot = grot;
1721 Vector3 AXimpulsei = impulsei; 2086 Vector3 AXimpulsei = impulsei;
1722 Vector3 newimpulse = AXimpulsei * AXgrot; 2087 Vector3 newimpulse = AXimpulsei * AXgrot;
1723 impulse = newimpulse; 2088 */
2089 torque *= GetWorldRotation();
1724 } 2090 }
1725 2091
1726 ParentGroup.setAngularImpulse(impulse); 2092 Torque = torque;
1727 } 2093 }
1728 2094
1729 /// <summary> 2095 /// <summary>
@@ -1731,7 +2097,9 @@ namespace OpenSim.Region.Framework.Scenes
1731 /// </summary> 2097 /// </summary>
1732 /// <param name="rootObjectFlags"></param> 2098 /// <param name="rootObjectFlags"></param>
1733 /// <param name="VolumeDetectActive"></param> 2099 /// <param name="VolumeDetectActive"></param>
1734 public void ApplyPhysics(uint rootObjectFlags, bool _VolumeDetectActive) 2100 /// <param name="building"></param>
2101
2102 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1735 { 2103 {
1736 VolumeDetectActive = _VolumeDetectActive; 2104 VolumeDetectActive = _VolumeDetectActive;
1737 2105
@@ -1741,8 +2109,8 @@ namespace OpenSim.Region.Framework.Scenes
1741 if (PhysicsShapeType == (byte)PhysShapeType.none) 2109 if (PhysicsShapeType == (byte)PhysShapeType.none)
1742 return; 2110 return;
1743 2111
1744 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2112 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1745 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2113 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1746 2114
1747 if (_VolumeDetectActive) 2115 if (_VolumeDetectActive)
1748 isPhantom = true; 2116 isPhantom = true;
@@ -1757,7 +2125,8 @@ namespace OpenSim.Region.Framework.Scenes
1757 && !ParentGroup.IsAttachmentCheckFull() 2125 && !ParentGroup.IsAttachmentCheckFull()
1758 && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 2126 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1759 { 2127 {
1760 AddToPhysics(isPhysical, isPhantom, isPhysical); 2128 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
2129 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1761 } 2130 }
1762 else 2131 else
1763 PhysActor = null; // just to be sure 2132 PhysActor = null; // just to be sure
@@ -1786,7 +2155,7 @@ namespace OpenSim.Region.Framework.Scenes
1786 /// <param name="linkNum"></param> 2155 /// <param name="linkNum"></param>
1787 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 2156 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1788 /// <returns></returns> 2157 /// <returns></returns>
1789 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 2158 public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1790 { 2159 {
1791 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2160 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1792 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator 2161 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
@@ -1816,6 +2185,12 @@ namespace OpenSim.Region.Framework.Scenes
1816 dupe.Category = Category; 2185 dupe.Category = Category;
1817 dupe.m_rezzed = m_rezzed; 2186 dupe.m_rezzed = m_rezzed;
1818 2187
2188 dupe.m_UndoRedo = null;
2189 dupe.m_isSelected = false;
2190
2191 dupe.IgnoreUndoUpdate = false;
2192 dupe.Undoing = false;
2193
1819 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2194 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1820 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2195 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1821 2196
@@ -1830,7 +2205,8 @@ namespace OpenSim.Region.Framework.Scenes
1830 } 2205 }
1831 2206
1832 // Move afterwards ResetIDs as it clears the localID 2207 // Move afterwards ResetIDs as it clears the localID
1833 dupe.LocalId = localID; 2208 dupe.LocalId = plocalID;
2209
1834 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2210 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1835 dupe.LastOwnerID = OwnerID; 2211 dupe.LastOwnerID = OwnerID;
1836 2212
@@ -1857,8 +2233,12 @@ namespace OpenSim.Region.Framework.Scenes
1857*/ 2233*/
1858 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2234 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1859 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2235 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2236// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1860 } 2237 }
1861 2238
2239 if (dupe.PhysActor != null)
2240 dupe.PhysActor.LocalID = plocalID;
2241
1862 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2242 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1863 2243
1864// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2244// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1877,10 +2257,10 @@ namespace OpenSim.Region.Framework.Scenes
1877 { 2257 {
1878 if (asset != null) 2258 if (asset != null)
1879 SculptTextureCallback(asset); 2259 SculptTextureCallback(asset);
1880 else 2260// else
1881 m_log.WarnFormat( 2261// m_log.WarnFormat(
1882 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2262// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1883 Name, UUID, id); 2263// Name, UUID, id);
1884 } 2264 }
1885*/ 2265*/
1886 /// <summary> 2266 /// <summary>
@@ -1979,6 +2359,7 @@ namespace OpenSim.Region.Framework.Scenes
1979 2359
1980 /// <summary> 2360 /// <summary>
1981 /// Do a physics propery update for this part. 2361 /// Do a physics propery update for this part.
2362 /// now also updates phantom and volume detector
1982 /// </summary> 2363 /// </summary>
1983 /// <param name="UsePhysics"></param> 2364 /// <param name="UsePhysics"></param>
1984 /// <param name="isNew"></param> 2365 /// <param name="isNew"></param>
@@ -2004,64 +2385,69 @@ namespace OpenSim.Region.Framework.Scenes
2004 { 2385 {
2005 if (pa.IsPhysical) // implies UsePhysics==false for this block 2386 if (pa.IsPhysical) // implies UsePhysics==false for this block
2006 { 2387 {
2007 if (!isNew) 2388 if (!isNew) // implies UsePhysics==false for this block
2389 {
2008 ParentGroup.Scene.RemovePhysicalPrim(1); 2390 ParentGroup.Scene.RemovePhysicalPrim(1);
2009 2391
2010 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2392 Velocity = new Vector3(0, 0, 0);
2011 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2393 Acceleration = new Vector3(0, 0, 0);
2012 pa.delink(); 2394 if (ParentGroup.RootPart == this)
2395 AngularVelocity = new Vector3(0, 0, 0);
2013 2396
2014 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2397 if (pa.Phantom && !VolumeDetectActive)
2015 { 2398 {
2016 // destroy all joints connected to this now deactivated body 2399 RemoveFromPhysics();
2017 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2400 return;
2018 } 2401 }
2019 2402
2020 // stop client-side interpolation of all joint proxy objects that have just been deleted 2403 pa.IsPhysical = UsePhysics;
2021 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2404 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
2022 // which stops client-side interpolation of deactivated joint proxy objects. 2405 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2406 pa.delink();
2407 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2408 {
2409 // destroy all joints connected to this now deactivated body
2410 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2411 }
2412 }
2023 } 2413 }
2024 2414
2025 if (!UsePhysics && !isNew) 2415 if (pa.IsPhysical != UsePhysics)
2026 { 2416 pa.IsPhysical = UsePhysics;
2027 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
2028 // prim still has velocity and continues to interpolate its position along the old
2029 // velocity-vector.
2030 Velocity = new Vector3(0, 0, 0);
2031 Acceleration = new Vector3(0, 0, 0);
2032 AngularVelocity = new Vector3(0, 0, 0);
2033 //RotationalVelocity = new Vector3(0, 0, 0);
2034 }
2035 2417
2036 pa.IsPhysical = UsePhysics; 2418 if (UsePhysics)
2419 {
2420 if (ParentGroup.RootPart.KeyframeMotion != null)
2421 ParentGroup.RootPart.KeyframeMotion.Stop();
2422 ParentGroup.RootPart.KeyframeMotion = null;
2423 ParentGroup.Scene.AddPhysicalPrim(1);
2037 2424
2038 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2425 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2039 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2426 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
2040 /// that's not wholesome. Had to make Scene public
2041 //PhysActor = null;
2042 2427
2043 if ((Flags & PrimFlags.Phantom) == 0) 2428 if (ParentID != 0 && ParentID != LocalId)
2044 {
2045 if (UsePhysics)
2046 { 2429 {
2047 if (ParentGroup.RootPart.KeyframeMotion != null) 2430 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2048 ParentGroup.RootPart.KeyframeMotion.Stop();
2049 ParentGroup.RootPart.KeyframeMotion = null;
2050 ParentGroup.Scene.AddPhysicalPrim(1);
2051
2052 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2053 pa.OnOutOfBounds += PhysicsOutOfBounds;
2054 if (ParentID != 0 && ParentID != LocalId)
2055 {
2056 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2057 2431
2058 if (parentPa != null) 2432 if (parentPa != null)
2059 { 2433 {
2060 pa.link(parentPa); 2434 pa.link(parentPa);
2061 }
2062 } 2435 }
2063 } 2436 }
2064 } 2437 }
2438 }
2439
2440 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2441 if (pa.Phantom != phan)
2442 pa.Phantom = phan;
2443
2444// some engines dont' have this check still
2445// if (VolumeDetectActive != pa.IsVolumeDtc)
2446 {
2447 if (VolumeDetectActive)
2448 pa.SetVolumeDetect(1);
2449 else
2450 pa.SetVolumeDetect(0);
2065 } 2451 }
2066 2452
2067 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2453 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -2132,13 +2518,8 @@ namespace OpenSim.Region.Framework.Scenes
2132 2518
2133 public int GetAxisRotation(int axis) 2519 public int GetAxisRotation(int axis)
2134 { 2520 {
2135 //Cannot use ScriptBaseClass constants as no referance to it currently. 2521 if (!ParentGroup.IsDeleted)
2136 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) 2522 return ParentGroup.GetAxisRotation(axis);
2137 return STATUS_ROTATE_X;
2138 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
2139 return STATUS_ROTATE_Y;
2140 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
2141 return STATUS_ROTATE_Z;
2142 2523
2143 return 0; 2524 return 0;
2144 } 2525 }
@@ -2164,42 +2545,63 @@ namespace OpenSim.Region.Framework.Scenes
2164 2545
2165 public Vector3 GetGeometricCenter() 2546 public Vector3 GetGeometricCenter()
2166 { 2547 {
2548 // this is not real geometric center but a average of positions relative to root prim acording to
2549 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
2550 // ignoring tortured prims details since sl also seems to ignore
2551 // so no real use in doing it on physics
2552 if (ParentGroup.IsDeleted)
2553 return new Vector3(0, 0, 0);
2554
2555 return ParentGroup.GetGeometricCenter();
2556 }
2557
2558 public float GetMass()
2559 {
2167 PhysicsActor pa = PhysActor; 2560 PhysicsActor pa = PhysActor;
2168 2561
2169 if (pa != null) 2562 if (pa != null)
2170 return pa.GeometricCenter; 2563 return pa.Mass;
2171 else 2564 else
2172 return Vector3.Zero; 2565 return 0;
2173 } 2566 }
2174 2567
2175 public Vector3 GetCenterOfMass() 2568 public Vector3 GetCenterOfMass()
2176 { 2569 {
2570 if (ParentGroup.RootPart == this)
2571 {
2572 if (ParentGroup.IsDeleted)
2573 return AbsolutePosition;
2574 return ParentGroup.GetCenterOfMass();
2575 }
2576
2177 PhysicsActor pa = PhysActor; 2577 PhysicsActor pa = PhysActor;
2178 2578
2179 if (pa != null) 2579 if (pa != null)
2180 return pa.CenterOfMass; 2580 {
2581 Vector3 tmp = pa.CenterOfMass;
2582 return tmp;
2583 }
2181 else 2584 else
2182 return Vector3.Zero; 2585 return AbsolutePosition;
2183 } 2586 }
2184 2587
2185 public float GetMass() 2588 public Vector3 GetPartCenterOfMass()
2186 { 2589 {
2187 PhysicsActor pa = PhysActor; 2590 PhysicsActor pa = PhysActor;
2188 2591
2189 if (pa != null) 2592 if (pa != null)
2190 return pa.Mass; 2593 {
2594 Vector3 tmp = pa.CenterOfMass;
2595 return tmp;
2596 }
2191 else 2597 else
2192 return 0; 2598 return AbsolutePosition;
2193 } 2599 }
2194 2600
2601
2195 public Vector3 GetForce() 2602 public Vector3 GetForce()
2196 { 2603 {
2197 PhysicsActor pa = PhysActor; 2604 return Force;
2198
2199 if (pa != null)
2200 return pa.Force;
2201 else
2202 return Vector3.Zero;
2203 } 2605 }
2204 2606
2205 /// <summary> 2607 /// <summary>
@@ -2314,6 +2716,7 @@ namespace OpenSim.Region.Framework.Scenes
2314 detobj.velVector = obj.Velocity; 2716 detobj.velVector = obj.Velocity;
2315 detobj.colliderType = 0; 2717 detobj.colliderType = 0;
2316 detobj.groupUUID = obj.GroupID; 2718 detobj.groupUUID = obj.GroupID;
2719 detobj.linkNumber = LinkNum; // pass my link number
2317 2720
2318 return detobj; 2721 return detobj;
2319 } 2722 }
@@ -2329,6 +2732,7 @@ namespace OpenSim.Region.Framework.Scenes
2329 detobj.velVector = av.Velocity; 2732 detobj.velVector = av.Velocity;
2330 detobj.colliderType = 0; 2733 detobj.colliderType = 0;
2331 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 2734 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2735 detobj.linkNumber = LinkNum; // pass my link number
2332 2736
2333 return detobj; 2737 return detobj;
2334 } 2738 }
@@ -2344,6 +2748,7 @@ namespace OpenSim.Region.Framework.Scenes
2344 detobj.velVector = Vector3.Zero; 2748 detobj.velVector = Vector3.Zero;
2345 detobj.colliderType = 0; 2749 detobj.colliderType = 0;
2346 detobj.groupUUID = UUID.Zero; 2750 detobj.groupUUID = UUID.Zero;
2751 detobj.linkNumber = LinkNum; // pass my link number not sure needed.. but no harm
2347 2752
2348 return detobj; 2753 return detobj;
2349 } 2754 }
@@ -2393,7 +2798,7 @@ namespace OpenSim.Region.Framework.Scenes
2393 CollidingMessage = CreateColliderArgs(this, colliders); 2798 CollidingMessage = CreateColliderArgs(this, colliders);
2394 2799
2395 if (CollidingMessage.Colliders.Count > 0) 2800 if (CollidingMessage.Colliders.Count > 0)
2396 DoNotify(notify, LocalId, CollidingMessage); 2801 notify(LocalId, CollidingMessage);
2397 2802
2398 if (PassCollisions) 2803 if (PassCollisions)
2399 sendToRoot = true; 2804 sendToRoot = true;
@@ -2407,48 +2812,32 @@ namespace OpenSim.Region.Framework.Scenes
2407 { 2812 {
2408 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); 2813 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders);
2409 if (CollidingMessage.Colliders.Count > 0) 2814 if (CollidingMessage.Colliders.Count > 0)
2410 DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage); 2815 notify(ParentGroup.RootPart.LocalId, CollidingMessage);
2411 } 2816 }
2412 } 2817 }
2413 } 2818 }
2414 2819
2415 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2820 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2416 { 2821 {
2417 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2822 bool sendToRoot = true;
2418 {
2419 ColliderArgs LandCollidingMessage = new ColliderArgs();
2420 List<DetectedObject> colliding = new List<DetectedObject>();
2421
2422 colliding.Add(CreateDetObjectForGround());
2423 LandCollidingMessage.Colliders = colliding;
2424 2823
2425 DoNotify(notify, LocalId, LandCollidingMessage); 2824 ColliderArgs LandCollidingMessage = new ColliderArgs();
2426 } 2825 List<DetectedObject> colliding = new List<DetectedObject>();
2427 } 2826
2827 colliding.Add(CreateDetObjectForGround());
2828 LandCollidingMessage.Colliders = colliding;
2428 2829
2429 private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs) 2830 if (Inventory.ContainsScripts())
2430 {
2431 if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions)
2432 { 2831 {
2433 // For those learning C#, FireAndForget takes a function, an object to pass 2832 if (!PassCollisions)
2434 // to that function and an ID string. The "oo => {}" construct is a lambda expression 2833 sendToRoot = false;
2435 // for a function with one arguement ('oo'). The 'new Object[] {}" construct creates an Object
2436 // that is an object array and initializes it with three items (the parameters
2437 // being passed). The parameters passed are the function to call ('notify') and
2438 // its two arguements. Finally, once in the function (called later by the FireAndForget
2439 // thread scheduler), the passed object is cast to an object array and then each
2440 // of its items (aoo[0] to aoo[2]) are individually cast to what they are and
2441 // then used in a call of the passed ScriptCollidingNotification function.
2442 Util.FireAndForget(oo =>
2443 {
2444 Object[] aoo = (Object[])oo;
2445 ((ScriptCollidingNotification)aoo[0])((uint)aoo[1], (ColliderArgs)aoo[2]);
2446
2447 }, new Object[] { notify, id, collargs }, "SOP.Collision");
2448 } 2834 }
2449 else 2835 if ((ScriptEvents & ev) != 0)
2836 notify(LocalId, LandCollidingMessage);
2837
2838 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2450 { 2839 {
2451 notify(id, collargs); 2840 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2452 } 2841 }
2453 } 2842 }
2454 2843
@@ -2464,44 +2853,81 @@ namespace OpenSim.Region.Framework.Scenes
2464 List<uint> endedColliders = new List<uint>(); 2853 List<uint> endedColliders = new List<uint>();
2465 List<uint> startedColliders = new List<uint>(); 2854 List<uint> startedColliders = new List<uint>();
2466 2855
2467 // calculate things that started colliding this time 2856 if (collissionswith.Count == 0)
2468 // and build up list of colliders this time
2469 foreach (uint localid in collissionswith.Keys)
2470 { 2857 {
2471 thisHitColliders.Add(localid); 2858 if (m_lastColliders.Count == 0)
2472 if (!m_lastColliders.Contains(localid)) 2859 return; // nothing to do
2473 startedColliders.Add(localid);
2474 }
2475 2860
2476 // calculate things that ended colliding 2861 foreach (uint localID in m_lastColliders)
2477 foreach (uint localID in m_lastColliders) 2862 {
2478 {
2479 if (!thisHitColliders.Contains(localID))
2480 endedColliders.Add(localID); 2863 endedColliders.Add(localID);
2864 }
2865 m_lastColliders.Clear();
2481 } 2866 }
2482 2867
2483 //add the items that started colliding this time to the last colliders list. 2868 else
2484 foreach (uint localID in startedColliders) 2869 {
2485 m_lastColliders.Add(localID); 2870 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2486 2871
2487 // remove things that ended colliding from the last colliders list 2872 // calculate things that started colliding this time
2488 foreach (uint localID in endedColliders) 2873 // and build up list of colliders this time
2489 m_lastColliders.Remove(localID); 2874 if (!VolumeDetectActive && CollisionSoundType >= 0)
2875 {
2876 CollisionForSoundInfo soundinfo;
2877 ContactPoint curcontact;
2490 2878
2491 // play the sound. 2879 foreach (uint id in collissionswith.Keys)
2492 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2880 {
2493 { 2881 thisHitColliders.Add(id);
2494 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2882 if (!m_lastColliders.Contains(id))
2495 if (soundModule != null) 2883 {
2884 startedColliders.Add(id);
2885
2886 curcontact = collissionswith[id];
2887 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2888 {
2889 soundinfo = new CollisionForSoundInfo();
2890 soundinfo.colliderID = id;
2891 soundinfo.position = curcontact.Position;
2892 soundinfo.relativeVel = curcontact.RelativeSpeed;
2893 soundinfolist.Add(soundinfo);
2894 }
2895 }
2896 }
2897 }
2898 else
2899 {
2900 foreach (uint id in collissionswith.Keys)
2901 {
2902 thisHitColliders.Add(id);
2903 if (!m_lastColliders.Contains(id))
2904 startedColliders.Add(id);
2905 }
2906 }
2907
2908 // calculate things that ended colliding
2909 foreach (uint localID in m_lastColliders)
2496 { 2910 {
2497 soundModule.SendSound(UUID, CollisionSound, 2911 if (!thisHitColliders.Contains(localID))
2498 CollisionSoundVolume, true, 0, 0, false, 2912 endedColliders.Add(localID);
2499 false);
2500 } 2913 }
2914
2915 //add the items that started colliding this time to the last colliders list.
2916 foreach (uint localID in startedColliders)
2917 m_lastColliders.Add(localID);
2918
2919 // remove things that ended colliding from the last colliders list
2920 foreach (uint localID in endedColliders)
2921 m_lastColliders.Remove(localID);
2922
2923 // play sounds.
2924 if (soundinfolist.Count > 0)
2925 CollisionSounds.PartCollisionSound(this, soundinfolist);
2501 } 2926 }
2502 2927
2503 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2928 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2504 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2929 if (!VolumeDetectActive)
2930 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2505 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2931 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2506 2932
2507 if (startedColliders.Contains(0)) 2933 if (startedColliders.Contains(0))
@@ -2512,6 +2938,35 @@ namespace OpenSim.Region.Framework.Scenes
2512 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2938 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2513 } 2939 }
2514 2940
2941 // The Collision sounds code calls this
2942 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
2943 {
2944 if (soundID == UUID.Zero)
2945 return;
2946
2947 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2948 if (soundModule == null)
2949 return;
2950
2951 if (volume > 1)
2952 volume = 1;
2953 if (volume < 0)
2954 volume = 0;
2955
2956 int now = Util.EnvironmentTickCount();
2957 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
2958 return;
2959
2960 LastColSoundSentTime = now;
2961
2962 UUID ownerID = OwnerID;
2963 UUID objectID = ParentGroup.RootPart.UUID;
2964 UUID parentID = ParentGroup.UUID;
2965 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2966
2967 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2968 }
2969
2515 public void PhysicsOutOfBounds(Vector3 pos) 2970 public void PhysicsOutOfBounds(Vector3 pos)
2516 { 2971 {
2517 // Note: This is only being called on the root prim at this time. 2972 // Note: This is only being called on the root prim at this time.
@@ -2539,7 +2994,7 @@ namespace OpenSim.Region.Framework.Scenes
2539 } 2994 }
2540 //ParentGroup.RootPart.m_groupPosition = newpos; 2995 //ParentGroup.RootPart.m_groupPosition = newpos;
2541 } 2996 }
2542 2997/* ubit: there are no flexible links
2543 if (pa != null && ParentID != 0 && ParentGroup != null) 2998 if (pa != null && ParentID != 0 && ParentGroup != null)
2544 { 2999 {
2545 // Special case where a child object is requesting property updates. 3000 // Special case where a child object is requesting property updates.
@@ -2559,7 +3014,7 @@ namespace OpenSim.Region.Framework.Scenes
2559 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}", 3014 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2560 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset); 3015 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2561 } 3016 }
2562 3017*/
2563 ScheduleTerseUpdate(); 3018 ScheduleTerseUpdate();
2564 } 3019 }
2565 3020
@@ -2619,18 +3074,17 @@ namespace OpenSim.Region.Framework.Scenes
2619 3074
2620 if (ParentGroup.Scene != null) 3075 if (ParentGroup.Scene != null)
2621 { 3076 {
2622 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); 3077 float minsize = ParentGroup.Scene.m_minNonphys;
2623 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); 3078 float maxsize = ParentGroup.Scene.m_maxNonphys;
2624 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2625
2626 if (pa != null && pa.IsPhysical) 3079 if (pa != null && pa.IsPhysical)
2627 { 3080 {
2628 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); 3081 minsize = ParentGroup.Scene.m_minPhys;
2629 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); 3082 maxsize = ParentGroup.Scene.m_maxPhys;
2630 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); 3083 }
2631 } 3084 scale.X = Util.Clamp(scale.X, minsize, maxsize);
3085 scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
3086 scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
2632 } 3087 }
2633
2634// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 3088// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
2635 3089
2636 Scale = scale; 3090 Scale = scale;
@@ -2812,7 +3266,19 @@ namespace OpenSim.Region.Framework.Scenes
2812 3266
2813// m_log.DebugFormat( 3267// m_log.DebugFormat(
2814// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); 3268// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
2815 3269
3270
3271 if (ParentGroup.IsAttachment)
3272 {
3273 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3274 if (sp != null)
3275 {
3276 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3277 }
3278 }
3279
3280/* this does nothing
3281SendFullUpdateToClient(remoteClient, Position) ignores position parameter
2816 if (IsRoot) 3282 if (IsRoot)
2817 { 3283 {
2818 if (ParentGroup.IsAttachment) 3284 if (ParentGroup.IsAttachment)
@@ -2824,6 +3290,7 @@ namespace OpenSim.Region.Framework.Scenes
2824 SendFullUpdateToClient(remoteClient, AbsolutePosition); 3290 SendFullUpdateToClient(remoteClient, AbsolutePosition);
2825 } 3291 }
2826 } 3292 }
3293*/
2827 else 3294 else
2828 { 3295 {
2829 SendFullUpdateToClient(remoteClient); 3296 SendFullUpdateToClient(remoteClient);
@@ -2833,17 +3300,55 @@ namespace OpenSim.Region.Framework.Scenes
2833 /// <summary> 3300 /// <summary>
2834 /// Send a full update for this part to all clients. 3301 /// Send a full update for this part to all clients.
2835 /// </summary> 3302 /// </summary>
2836 public void SendFullUpdateToAllClients() 3303 public void SendFullUpdateToAllClientsInternal()
2837 { 3304 {
2838 if (ParentGroup == null) 3305 if (ParentGroup == null)
2839 return; 3306 return;
2840 3307
3308 // Update the "last" values
3309 m_lastPosition = OffsetPosition;
3310 m_lastRotation = RotationOffset;
3311 m_lastVelocity = Velocity;
3312 m_lastAcceleration = Acceleration;
3313 m_lastAngularVelocity = AngularVelocity;
3314 m_lastUpdateSentTime = Environment.TickCount;
3315
2841 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3316 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2842 { 3317 {
2843 SendFullUpdate(avatar.ControllingClient); 3318 SendFullUpdate(avatar.ControllingClient);
2844 }); 3319 });
2845 } 3320 }
2846 3321
3322 public void SendFullUpdateToAllClients()
3323 {
3324 if (ParentGroup == null)
3325 return;
3326
3327 // Update the "last" values
3328 m_lastPosition = OffsetPosition;
3329 m_lastRotation = RotationOffset;
3330 m_lastVelocity = Velocity;
3331 m_lastAcceleration = Acceleration;
3332 m_lastAngularVelocity = AngularVelocity;
3333 m_lastUpdateSentTime = Environment.TickCount;
3334
3335 if (ParentGroup.IsAttachment)
3336 {
3337 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3338 if (sp != null)
3339 {
3340 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3341 }
3342 }
3343 else
3344 {
3345 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3346 {
3347 SendFullUpdate(avatar.ControllingClient);
3348 });
3349 }
3350 }
3351
2847 /// <summary> 3352 /// <summary>
2848 /// Sends a full update to the client 3353 /// Sends a full update to the client
2849 /// </summary> 3354 /// </summary>
@@ -2864,9 +3369,9 @@ namespace OpenSim.Region.Framework.Scenes
2864 return; 3369 return;
2865 3370
2866 // Suppress full updates during attachment editing 3371 // Suppress full updates during attachment editing
2867 // 3372 // sl Does send them
2868 if (ParentGroup.IsSelected && ParentGroup.IsAttachment) 3373 // if (ParentGroup.IsSelected && ParentGroup.IsAttachment)
2869 return; 3374 // return;
2870 3375
2871 if (ParentGroup.IsDeleted) 3376 if (ParentGroup.IsDeleted)
2872 return; 3377 return;
@@ -2896,8 +3401,8 @@ namespace OpenSim.Region.Framework.Scenes
2896 { 3401 {
2897 const float ROTATION_TOLERANCE = 0.01f; 3402 const float ROTATION_TOLERANCE = 0.01f;
2898 const float VELOCITY_TOLERANCE = 0.001f; 3403 const float VELOCITY_TOLERANCE = 0.001f;
2899 const float POSITION_TOLERANCE = 0.05f; 3404 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2900 const int TIME_MS_TOLERANCE = 3000; 3405 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2901 3406
2902 switch (UpdateFlag) 3407 switch (UpdateFlag)
2903 { 3408 {
@@ -2911,40 +3416,74 @@ namespace OpenSim.Region.Framework.Scenes
2911 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3416 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
2912 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3417 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
2913 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3418 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
2914 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3419 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
2915 { 3420 {
2916 SendTerseUpdateToAllClients(); 3421 SendTerseUpdateToAllClientsInternal();
2917
2918 // Update the "last" values
2919 m_lastPosition = OffsetPosition;
2920 m_lastRotation = RotationOffset;
2921 m_lastVelocity = Velocity;
2922 m_lastAcceleration = Acceleration;
2923 m_lastAngularVelocity = AngularVelocity;
2924 m_lastTerseSent = Environment.TickCount;
2925 } 3422 }
2926 break; 3423 break;
2927 } 3424 }
2928 case UpdateRequired.FULL: 3425 case UpdateRequired.FULL:
2929 { 3426 {
2930 ClearUpdateSchedule(); 3427 ClearUpdateSchedule();
2931 SendFullUpdateToAllClients(); 3428 SendFullUpdateToAllClientsInternal();
2932 break; 3429 break;
2933 } 3430 }
2934 } 3431 }
2935 } 3432 }
2936 3433
3434
2937 /// <summary> 3435 /// <summary>
2938 /// Send a terse update to all clients 3436 /// Send a terse update to all clients
2939 /// </summary> 3437 /// </summary>
2940 public void SendTerseUpdateToAllClients() 3438 public void SendTerseUpdateToAllClientsInternal()
2941 { 3439 {
3440 if (ParentGroup == null || ParentGroup.Scene == null)
3441 return;
3442
3443 // Update the "last" values
3444 m_lastPosition = OffsetPosition;
3445 m_lastRotation = RotationOffset;
3446 m_lastVelocity = Velocity;
3447 m_lastAcceleration = Acceleration;
3448 m_lastAngularVelocity = AngularVelocity;
3449 m_lastUpdateSentTime = Environment.TickCount;
3450
2942 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3451 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2943 { 3452 {
2944 SendTerseUpdateToClient(client); 3453 SendTerseUpdateToClient(client);
2945 }); 3454 });
2946 } 3455 }
2947 3456
3457 public void SendTerseUpdateToAllClients()
3458 {
3459 if (ParentGroup == null || ParentGroup.Scene == null)
3460 return;
3461
3462 // Update the "last" values
3463 m_lastPosition = OffsetPosition;
3464 m_lastRotation = RotationOffset;
3465 m_lastVelocity = Velocity;
3466 m_lastAcceleration = Acceleration;
3467 m_lastAngularVelocity = AngularVelocity;
3468 m_lastUpdateSentTime = Environment.TickCount;
3469
3470 if (ParentGroup.IsAttachment)
3471 {
3472 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3473 if (sp != null)
3474 {
3475 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3476 }
3477 }
3478 else
3479 {
3480 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3481 {
3482 SendTerseUpdateToClient(client);
3483 });
3484 }
3485 }
3486
2948 public void SetAxisRotation(int axis, int rotate) 3487 public void SetAxisRotation(int axis, int rotate)
2949 { 3488 {
2950 ParentGroup.SetAxisRotation(axis, rotate); 3489 ParentGroup.SetAxisRotation(axis, rotate);
@@ -2962,10 +3501,13 @@ namespace OpenSim.Region.Framework.Scenes
2962 3501
2963 public void SetBuoyancy(float fvalue) 3502 public void SetBuoyancy(float fvalue)
2964 { 3503 {
2965 PhysicsActor pa = PhysActor; 3504 Buoyancy = fvalue;
2966 3505/*
2967 if (pa != null) 3506 if (PhysActor != null)
2968 pa.Buoyancy = fvalue; 3507 {
3508 PhysActor.Buoyancy = fvalue;
3509 }
3510 */
2969 } 3511 }
2970 3512
2971 public void SetDieAtEdge(bool p) 3513 public void SetDieAtEdge(bool p)
@@ -2981,47 +3523,111 @@ namespace OpenSim.Region.Framework.Scenes
2981 PhysicsActor pa = PhysActor; 3523 PhysicsActor pa = PhysActor;
2982 3524
2983 if (pa != null) 3525 if (pa != null)
2984 pa.FloatOnWater = floatYN == 1; 3526 pa.FloatOnWater = (floatYN == 1);
2985 } 3527 }
2986 3528
2987 public void SetForce(Vector3 force) 3529 public void SetForce(Vector3 force)
2988 { 3530 {
2989 PhysicsActor pa = PhysActor; 3531 Force = force;
3532 }
2990 3533
2991 if (pa != null) 3534 public SOPVehicle VehicleParams
2992 pa.Force = force; 3535 {
3536 get
3537 {
3538 return m_vehicleParams;
3539 }
3540 set
3541 {
3542 m_vehicleParams = value;
3543 }
3544 }
3545
3546
3547 public int VehicleType
3548 {
3549 get
3550 {
3551 if (m_vehicleParams == null)
3552 return (int)Vehicle.TYPE_NONE;
3553 else
3554 return (int)m_vehicleParams.Type;
3555 }
3556 set
3557 {
3558 SetVehicleType(value);
3559 }
2993 } 3560 }
2994 3561
2995 public void SetVehicleType(int type) 3562 public void SetVehicleType(int type)
2996 { 3563 {
2997 PhysicsActor pa = PhysActor; 3564 m_vehicleParams = null;
3565
3566 if (type == (int)Vehicle.TYPE_NONE)
3567 {
3568 if (_parentID ==0 && PhysActor != null)
3569 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3570 return;
3571 }
3572 m_vehicleParams = new SOPVehicle();
3573 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3574 {
3575 if (_parentID ==0 && PhysActor != null)
3576 PhysActor.VehicleType = type;
3577 return;
3578 }
3579 }
2998 3580
2999 if (pa != null) 3581 public void SetVehicleFlags(int param, bool remove)
3000 pa.VehicleType = type; 3582 {
3583 if (m_vehicleParams == null)
3584 return;
3585
3586 m_vehicleParams.ProcessVehicleFlags(param, remove);
3587
3588 if (_parentID ==0 && PhysActor != null)
3589 {
3590 PhysActor.VehicleFlags(param, remove);
3591 }
3001 } 3592 }
3002 3593
3003 public void SetVehicleFloatParam(int param, float value) 3594 public void SetVehicleFloatParam(int param, float value)
3004 { 3595 {
3005 PhysicsActor pa = PhysActor; 3596 if (m_vehicleParams == null)
3597 return;
3006 3598
3007 if (pa != null) 3599 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
3008 pa.VehicleFloatParam(param, value); 3600
3601 if (_parentID == 0 && PhysActor != null)
3602 {
3603 PhysActor.VehicleFloatParam(param, value);
3604 }
3009 } 3605 }
3010 3606
3011 public void SetVehicleVectorParam(int param, Vector3 value) 3607 public void SetVehicleVectorParam(int param, Vector3 value)
3012 { 3608 {
3013 PhysicsActor pa = PhysActor; 3609 if (m_vehicleParams == null)
3610 return;
3014 3611
3015 if (pa != null) 3612 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
3016 pa.VehicleVectorParam(param, value); 3613
3614 if (_parentID == 0 && PhysActor != null)
3615 {
3616 PhysActor.VehicleVectorParam(param, value);
3617 }
3017 } 3618 }
3018 3619
3019 public void SetVehicleRotationParam(int param, Quaternion rotation) 3620 public void SetVehicleRotationParam(int param, Quaternion rotation)
3020 { 3621 {
3021 PhysicsActor pa = PhysActor; 3622 if (m_vehicleParams == null)
3623 return;
3022 3624
3023 if (pa != null) 3625 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
3024 pa.VehicleRotationParam(param, rotation); 3626
3627 if (_parentID == 0 && PhysActor != null)
3628 {
3629 PhysActor.VehicleRotationParam(param, rotation);
3630 }
3025 } 3631 }
3026 3632
3027 /// <summary> 3633 /// <summary>
@@ -3222,14 +3828,6 @@ namespace OpenSim.Region.Framework.Scenes
3222 hasProfileCut = hasDimple; // is it the same thing? 3828 hasProfileCut = hasDimple; // is it the same thing?
3223 } 3829 }
3224 3830
3225 public void SetVehicleFlags(int param, bool remove)
3226 {
3227 PhysicsActor pa = PhysActor;
3228
3229 if (pa != null)
3230 pa.VehicleFlags(param, remove);
3231 }
3232
3233 public void SetGroup(UUID groupID, IClientAPI client) 3831 public void SetGroup(UUID groupID, IClientAPI client)
3234 { 3832 {
3235 // Scene.AddNewPrims() calls with client == null so can't use this. 3833 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3238,8 +3836,8 @@ namespace OpenSim.Region.Framework.Scenes
3238// Name, groupID, OwnerID); 3836// Name, groupID, OwnerID);
3239 3837
3240 GroupID = groupID; 3838 GroupID = groupID;
3241 if (client != null) 3839// if (client != null)
3242 SendPropertiesToClient(client); 3840// SendPropertiesToClient(client);
3243 UpdateFlag = UpdateRequired.FULL; 3841 UpdateFlag = UpdateRequired.FULL;
3244 } 3842 }
3245 3843
@@ -3263,7 +3861,7 @@ namespace OpenSim.Region.Framework.Scenes
3263 3861
3264 if (pa != null) 3862 if (pa != null)
3265 { 3863 {
3266 pa.LockAngularMotion(RotationAxis); 3864 pa.LockAngularMotion(RotationAxisLocks);
3267 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 3865 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
3268 } 3866 }
3269 } 3867 }
@@ -3334,67 +3932,16 @@ namespace OpenSim.Region.Framework.Scenes
3334 ParentGroup.StopMoveToTarget(); 3932 ParentGroup.StopMoveToTarget();
3335 } 3933 }
3336 3934
3337 public void StoreUndoState() 3935 public void StoreUndoState(ObjectChangeType change)
3338 { 3936 {
3339 StoreUndoState(false); 3937 if (m_UndoRedo == null)
3340 } 3938 m_UndoRedo = new UndoRedoState(5);
3341 3939
3342 public void StoreUndoState(bool forGroup) 3940 lock (m_UndoRedo)
3343 {
3344 if (ParentGroup == null || ParentGroup.Scene == null)
3345 return;
3346
3347 if (Undoing)
3348 {
3349// m_log.DebugFormat(
3350// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3351 return;
3352 }
3353
3354 if (IgnoreUndoUpdate)
3355 {
3356// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3357 return;
3358 }
3359
3360 lock (m_undo)
3361 { 3941 {
3362 if (m_undo.Count > 0) 3942 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3363 { 3943 {
3364 UndoState last = m_undo[m_undo.Count - 1]; 3944 m_UndoRedo.StoreUndo(this, change);
3365 if (last != null)
3366 {
3367 // TODO: May need to fix for group comparison
3368 if (last.Compare(this))
3369 {
3370// m_log.DebugFormat(
3371// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3372// Name, LocalId, m_undo.Count);
3373
3374 return;
3375 }
3376 }
3377 }
3378
3379// m_log.DebugFormat(
3380// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3381// Name, LocalId, forGroup, m_undo.Count);
3382
3383 if (ParentGroup.Scene.MaxUndoCount > 0)
3384 {
3385 UndoState nUndo = new UndoState(this, forGroup);
3386
3387 m_undo.Add(nUndo);
3388
3389 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3390 m_undo.RemoveAt(0);
3391
3392 if (m_redo.Count > 0)
3393 m_redo.Clear();
3394
3395// m_log.DebugFormat(
3396// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3397// Name, LocalId, forGroup, m_undo.Count);
3398 } 3945 }
3399 } 3946 }
3400 } 3947 }
@@ -3406,88 +3953,46 @@ namespace OpenSim.Region.Framework.Scenes
3406 { 3953 {
3407 get 3954 get
3408 { 3955 {
3409 lock (m_undo) 3956 if (m_UndoRedo == null)
3410 return m_undo.Count; 3957 return 0;
3958 return m_UndoRedo.Count;
3411 } 3959 }
3412 } 3960 }
3413 3961
3414 public void Undo() 3962 public void Undo()
3415 { 3963 {
3416 lock (m_undo) 3964 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3417 { 3965 return;
3418// m_log.DebugFormat(
3419// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3420// Name, LocalId, m_undo.Count);
3421
3422 if (m_undo.Count > 0)
3423 {
3424 UndoState goback = m_undo[m_undo.Count - 1];
3425 m_undo.RemoveAt(m_undo.Count - 1);
3426
3427 UndoState nUndo = null;
3428
3429 if (ParentGroup.Scene.MaxUndoCount > 0)
3430 {
3431 nUndo = new UndoState(this, goback.ForGroup);
3432 }
3433
3434 goback.PlaybackState(this);
3435
3436 if (nUndo != null)
3437 {
3438 m_redo.Add(nUndo);
3439
3440 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3441 m_redo.RemoveAt(0);
3442 }
3443 }
3444 3966
3445// m_log.DebugFormat( 3967 lock (m_UndoRedo)
3446// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3968 {
3447// Name, LocalId, m_undo.Count); 3969 Undoing = true;
3970 m_UndoRedo.Undo(this);
3971 Undoing = false;
3448 } 3972 }
3449 } 3973 }
3450 3974
3451 public void Redo() 3975 public void Redo()
3452 { 3976 {
3453 lock (m_undo) 3977 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3454 { 3978 return;
3455// m_log.DebugFormat(
3456// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3457// Name, LocalId, m_redo.Count);
3458
3459 if (m_redo.Count > 0)
3460 {
3461 UndoState gofwd = m_redo[m_redo.Count - 1];
3462 m_redo.RemoveAt(m_redo.Count - 1);
3463
3464 if (ParentGroup.Scene.MaxUndoCount > 0)
3465 {
3466 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3467
3468 m_undo.Add(nUndo);
3469
3470 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3471 m_undo.RemoveAt(0);
3472 }
3473
3474 gofwd.PlayfwdState(this);
3475 3979
3476// m_log.DebugFormat( 3980 lock (m_UndoRedo)
3477// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3981 {
3478// Name, LocalId, m_redo.Count); 3982 Undoing = true;
3479 } 3983 m_UndoRedo.Redo(this);
3984 Undoing = false;
3480 } 3985 }
3481 } 3986 }
3482 3987
3483 public void ClearUndoState() 3988 public void ClearUndoState()
3484 { 3989 {
3485// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3990 if (m_UndoRedo == null || Undoing)
3991 return;
3486 3992
3487 lock (m_undo) 3993 lock (m_UndoRedo)
3488 { 3994 {
3489 m_undo.Clear(); 3995 m_UndoRedo.Clear();
3490 m_redo.Clear();
3491 } 3996 }
3492 } 3997 }
3493 3998
@@ -4039,7 +4544,7 @@ namespace OpenSim.Region.Framework.Scenes
4039 if (god) 4544 if (god)
4040 { 4545 {
4041 BaseMask = ApplyMask(BaseMask, set, mask); 4546 BaseMask = ApplyMask(BaseMask, set, mask);
4042 Inventory.ApplyGodPermissions(_baseMask); 4547 Inventory.ApplyGodPermissions(BaseMask);
4043 } 4548 }
4044 4549
4045 break; 4550 break;
@@ -4070,7 +4575,7 @@ namespace OpenSim.Region.Framework.Scenes
4070 } 4575 }
4071 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4576 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
4072 baseMask; 4577 baseMask;
4073 // Prevent the client from creating no mod, no copy 4578 // Prevent the client from creating no copy, no transfer
4074 // objects 4579 // objects
4075 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4580 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
4076 NextOwnerMask |= (uint)PermissionMask.Transfer; 4581 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -4086,22 +4591,20 @@ namespace OpenSim.Region.Framework.Scenes
4086 4591
4087 public void ClonePermissions(SceneObjectPart source) 4592 public void ClonePermissions(SceneObjectPart source)
4088 { 4593 {
4089 bool update = false; 4594 uint prevOwnerMask = OwnerMask;
4595 uint prevGroupMask = GroupMask;
4596 uint prevEveryoneMask = EveryoneMask;
4597 uint prevNextOwnerMask = NextOwnerMask;
4090 4598
4091 if (BaseMask != source.BaseMask || 4599 OwnerMask = source.OwnerMask & BaseMask;
4092 OwnerMask != source.OwnerMask || 4600 GroupMask = source.GroupMask & BaseMask;
4093 GroupMask != source.GroupMask || 4601 EveryoneMask = source.EveryoneMask & BaseMask;
4094 EveryoneMask != source.EveryoneMask || 4602 NextOwnerMask = source.NextOwnerMask & BaseMask;
4095 NextOwnerMask != source.NextOwnerMask)
4096 update = true;
4097 4603
4098 BaseMask = source.BaseMask; 4604 if (OwnerMask != prevOwnerMask ||
4099 OwnerMask = source.OwnerMask; 4605 GroupMask != prevGroupMask ||
4100 GroupMask = source.GroupMask; 4606 EveryoneMask != prevEveryoneMask ||
4101 EveryoneMask = source.EveryoneMask; 4607 NextOwnerMask != prevNextOwnerMask)
4102 NextOwnerMask = source.NextOwnerMask;
4103
4104 if (update)
4105 SendFullUpdateToAllClients(); 4608 SendFullUpdateToAllClients();
4106 } 4609 }
4107 4610
@@ -4152,6 +4655,7 @@ namespace OpenSim.Region.Framework.Scenes
4152 } 4655 }
4153 } 4656 }
4154 4657
4658
4155 public void UpdateExtraPhysics(ExtraPhysicsData physdata) 4659 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4156 { 4660 {
4157 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null) 4661 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
@@ -4179,7 +4683,7 @@ namespace OpenSim.Region.Framework.Scenes
4179 /// <param name="SetTemporary"></param> 4683 /// <param name="SetTemporary"></param>
4180 /// <param name="SetPhantom"></param> 4684 /// <param name="SetPhantom"></param>
4181 /// <param name="SetVD"></param> 4685 /// <param name="SetVD"></param>
4182 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4686 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4183 { 4687 {
4184 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4688 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4185 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4689 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4189,99 +4693,104 @@ namespace OpenSim.Region.Framework.Scenes
4189 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4693 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4190 return; 4694 return;
4191 4695
4192 PhysicsActor pa = PhysActor; 4696 VolumeDetectActive = SetVD;
4193
4194 // Special cases for VD. VD can only be called from a script
4195 // and can't be combined with changes to other states. So we can rely
4196 // that...
4197 // ... if VD is changed, all others are not.
4198 // ... if one of the others is changed, VD is not.
4199 if (SetVD) // VD is active, special logic applies
4200 {
4201 // State machine logic for VolumeDetect
4202 // More logic below
4203 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4204 4697
4205 if (phanReset) // Phantom changes from on to off switch VD off too 4698 // volume detector implies phantom
4206 { 4699 if (VolumeDetectActive)
4207 SetVD = false; // Switch it of for the course of this routine
4208 VolumeDetectActive = false; // and also permanently
4209
4210 if (pa != null)
4211 pa.SetVolumeDetect(0); // Let physics know about it too
4212 }
4213 else
4214 {
4215 // If volumedetect is active we don't want phantom to be applied.
4216 // If this is a new call to VD out of the state "phantom"
4217 // this will also cause the prim to be visible to physics
4218 SetPhantom = false;
4219 }
4220 }
4221
4222 if (UsePhysics && IsJoint())
4223 {
4224 SetPhantom = true; 4700 SetPhantom = true;
4225 }
4226 4701
4227 if (UsePhysics) 4702 if (UsePhysics)
4228 {
4229 AddFlag(PrimFlags.Physics); 4703 AddFlag(PrimFlags.Physics);
4230 if (!wasUsingPhysics)
4231 {
4232 DoPhysicsPropertyUpdate(UsePhysics, false);
4233 }
4234 }
4235 else 4704 else
4236 {
4237 RemFlag(PrimFlags.Physics); 4705 RemFlag(PrimFlags.Physics);
4238 if (wasUsingPhysics)
4239 {
4240 DoPhysicsPropertyUpdate(UsePhysics, false);
4241 }
4242 }
4243 4706
4244 if (SetPhantom 4707 if (SetPhantom)
4245 || ParentGroup.IsAttachmentCheckFull()
4246 || PhysicsShapeType == (byte)PhysShapeType.none
4247 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4248 {
4249 AddFlag(PrimFlags.Phantom); 4708 AddFlag(PrimFlags.Phantom);
4709 else
4710 RemFlag(PrimFlags.Phantom);
4250 4711
4251 if (PhysActor != null) 4712 if (SetTemporary)
4713 AddFlag(PrimFlags.TemporaryOnRez);
4714 else
4715 RemFlag(PrimFlags.TemporaryOnRez);
4716
4717
4718 if (ParentGroup.Scene == null)
4719 return;
4720
4721 PhysicsActor pa = PhysActor;
4722
4723 if (pa != null && building && pa.Building != building)
4724 pa.Building = building;
4725
4726 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4727 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4728 {
4729 if (pa != null)
4252 { 4730 {
4731 if(wasUsingPhysics)
4732 ParentGroup.Scene.RemovePhysicalPrim(1);
4253 RemoveFromPhysics(); 4733 RemoveFromPhysics();
4254 pa = null;
4255 } 4734 }
4735
4736 Velocity = new Vector3(0, 0, 0);
4737 Acceleration = new Vector3(0, 0, 0);
4738 if (ParentGroup.RootPart == this)
4739 AngularVelocity = new Vector3(0, 0, 0);
4256 } 4740 }
4257 else // Not phantom 4741
4742 else
4258 { 4743 {
4259 RemFlag(PrimFlags.Phantom); 4744 if (ParentGroup.Scene.CollidablePrims)
4260
4261 if (ParentGroup.Scene == null)
4262 return;
4263
4264 if (ParentGroup.Scene.CollidablePrims && pa == null)
4265 { 4745 {
4266 AddToPhysics(UsePhysics, SetPhantom, false); 4746 if (pa == null)
4267 pa = PhysActor; 4747 {
4268 4748 AddToPhysics(UsePhysics, SetPhantom, building, false);
4269 if (pa != null) 4749 pa = PhysActor;
4750/*
4751 if (pa != null)
4752 {
4753 if (
4754// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4755// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4756// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4757// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4758// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4759// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4760 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4761 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4762 (CollisionSound != UUID.Zero)
4763 )
4764 {
4765 pa.OnCollisionUpdate += PhysicsCollision;
4766 pa.SubscribeEvents(1000);
4767 }
4768 }
4769*/
4770 if (pa != null)
4771 {
4772 pa.SetMaterial(Material);
4773 DoPhysicsPropertyUpdate(UsePhysics, true);
4774 }
4775 }
4776 else // it already has a physical representation
4270 { 4777 {
4271 pa.SetMaterial(Material);
4272 pa.Position = GetWorldPosition();
4273 pa.Orientation = GetWorldRotation();
4274 DoPhysicsPropertyUpdate(UsePhysics, true);
4275 4778
4276 SubscribeForCollisionEvents(); 4779 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4780/* moved into DoPhysicsPropertyUpdate
4781 if(VolumeDetectActive)
4782 pa.SetVolumeDetect(1);
4783 else
4784 pa.SetVolumeDetect(0);
4785*/
4786
4787 if (pa.Building != building)
4788 pa.Building = building;
4277 } 4789 }
4278 }
4279 else // it already has a physical representation
4280 {
4281 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4282 }
4283 }
4284 4790
4791 UpdatePhysicsSubscribedEvents();
4792 }
4793 }
4285 if (SetVD) 4794 if (SetVD)
4286 { 4795 {
4287 // If the above logic worked (this is urgent candidate to unit tests!) 4796 // If the above logic worked (this is urgent candidate to unit tests!)
@@ -4295,6 +4804,7 @@ namespace OpenSim.Region.Framework.Scenes
4295 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4804 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
4296 VolumeDetectActive = true; 4805 VolumeDetectActive = true;
4297 } 4806 }
4807 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4298 } 4808 }
4299 else if (SetVD != wasVD) 4809 else if (SetVD != wasVD)
4300 { 4810 {
@@ -4306,105 +4816,51 @@ namespace OpenSim.Region.Framework.Scenes
4306 RemFlag(PrimFlags.Phantom); 4816 RemFlag(PrimFlags.Phantom);
4307 VolumeDetectActive = false; 4817 VolumeDetectActive = false;
4308 } 4818 }
4309 4819 // and last in case we have a new actor and not building
4310 if (SetTemporary)
4311 {
4312 AddFlag(PrimFlags.TemporaryOnRez);
4313 }
4314 else
4315 {
4316 RemFlag(PrimFlags.TemporaryOnRez);
4317 }
4318
4319 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4320 4820
4321 if (ParentGroup != null) 4821 if (ParentGroup != null)
4322 { 4822 {
4323 ParentGroup.HasGroupChanged = true; 4823 ParentGroup.HasGroupChanged = true;
4324 ScheduleFullUpdate(); 4824 ScheduleFullUpdate();
4325 } 4825 }
4326 4826
4327// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4827// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4328 } 4828 }
4329 4829
4330 /// <summary> 4830 /// <summary>
4331 /// Subscribe for physics collision events if needed for scripts and sounds
4332 /// </summary>
4333 public void SubscribeForCollisionEvents()
4334 {
4335 PhysicsActor pa = PhysActor;
4336
4337 if (pa != null)
4338 {
4339 if (
4340 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4343 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4344 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4345 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4349 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4350 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4351 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4352 (CollisionSound != UUID.Zero)
4353 )
4354 {
4355 if (!pa.SubscribedEvents())
4356 {
4357 // If not already subscribed for event, set up for a collision event.
4358 pa.OnCollisionUpdate += PhysicsCollision;
4359 pa.SubscribeEvents(1000);
4360 }
4361 }
4362 else
4363 {
4364 // There is no need to be subscribed to collisions so, if subscribed, remove subscription
4365 if (pa.SubscribedEvents())
4366 {
4367 pa.OnCollisionUpdate -= PhysicsCollision;
4368 pa.UnSubscribeEvents();
4369 }
4370 }
4371 }
4372 }
4373
4374 /// <summary>
4375 /// Adds this part to the physics scene. 4831 /// Adds this part to the physics scene.
4832 /// and sets the PhysActor property
4376 /// </summary> 4833 /// </summary>
4377 /// <remarks>This method also sets the PhysActor property.</remarks> 4834 /// <param name="isPhysical">Add this prim as physical.</param>
4378 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4835 /// <param name="isPhantom">Add this prim as phantom.</param>
4379 /// <returns> 4836 /// <param name="building">tells physics to delay full construction of object</param>
4380 /// The physics actor. null if there was a failure. 4837 /// <param name="applyDynamics">applies velocities, force and torque</param>
4381 /// </returns> 4838 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4382 private void AddToPhysics(bool isPhysical, bool isPhantom, bool applyDynamics) 4839 {
4383 {
4384 PhysicsActor pa; 4840 PhysicsActor pa;
4385 4841
4386 Vector3 velocity = Velocity; 4842 Vector3 velocity = Velocity;
4387 Vector3 rotationalVelocity = AngularVelocity;; 4843 Vector3 rotationalVelocity = AngularVelocity;;
4388 4844
4389 try 4845 try
4390 { 4846 {
4391 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4847 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4392 string.Format("{0}/{1}", Name, UUID), 4848 string.Format("{0}/{1}", Name, UUID),
4393 Shape, 4849 Shape,
4394 AbsolutePosition, 4850 AbsolutePosition,
4395 Scale, 4851 Scale,
4396 GetWorldRotation(), 4852 GetWorldRotation(),
4397 isPhysical, 4853 isPhysical,
4398 isPhantom, 4854 isPhantom,
4399 PhysicsShapeType, 4855 PhysicsShapeType,
4400 m_localId); 4856 m_localId);
4401 } 4857 }
4402 catch (Exception e) 4858 catch (Exception e)
4403 { 4859 {
4404 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e); 4860 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
4405 pa = null; 4861 pa = null;
4406 } 4862 }
4407 4863
4408 if (pa != null) 4864 if (pa != null)
4409 { 4865 {
4410 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4866 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
@@ -4415,11 +4871,23 @@ namespace OpenSim.Region.Framework.Scenes
4415 pa.Friction = Friction; 4871 pa.Friction = Friction;
4416 pa.Restitution = Restitution; 4872 pa.Restitution = Restitution;
4417 4873
4874 if(LocalId == ParentGroup.RootPart.LocalId)
4875 {
4876 pa.LockAngularMotion(RotationAxisLocks);
4877 }
4878
4418 if (VolumeDetectActive) // change if not the default only 4879 if (VolumeDetectActive) // change if not the default only
4419 pa.SetVolumeDetect(1); 4880 pa.SetVolumeDetect(1);
4881
4882 if (m_vehicleParams != null && LocalId == ParentGroup.RootPart.LocalId)
4883 m_vehicleParams.SetVehicle(pa);
4884
4420 // we are going to tell rest of code about physics so better have this here 4885 // we are going to tell rest of code about physics so better have this here
4421 PhysActor = pa; 4886 PhysActor = pa;
4422 4887
4888 // DoPhysicsPropertyUpdate(isPhysical, true);
4889 // lets expand it here just with what it really needs to do
4890
4423 if (isPhysical) 4891 if (isPhysical)
4424 { 4892 {
4425 if (ParentGroup.RootPart.KeyframeMotion != null) 4893 if (ParentGroup.RootPart.KeyframeMotion != null)
@@ -4441,19 +4909,34 @@ namespace OpenSim.Region.Framework.Scenes
4441 } 4909 }
4442 } 4910 }
4443 4911
4444 if (applyDynamics) 4912 if (applyDynamics)
4445 // do independent of isphysical so parameters get setted (at least some) 4913 // do independent of isphysical so parameters get setted (at least some)
4446 { 4914 {
4447 Velocity = velocity; 4915 Velocity = velocity;
4448 AngularVelocity = rotationalVelocity; 4916 AngularVelocity = rotationalVelocity;
4449// pa.Velocity = velocity; 4917// pa.Velocity = velocity;
4450 pa.RotationalVelocity = rotationalVelocity; 4918 pa.RotationalVelocity = rotationalVelocity;
4919
4920 // if not vehicle and root part apply force and torque
4921 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE)
4922 && LocalId == ParentGroup.RootPart.LocalId)
4923 {
4924 pa.Force = Force;
4925 pa.Torque = Torque;
4926 }
4451 } 4927 }
4452 4928
4453 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 4929// if (Shape.SculptEntry)
4930// CheckSculptAndLoad();
4931// else
4932 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4933
4934 if (!building)
4935 pa.Building = false;
4454 } 4936 }
4455 4937
4456 PhysActor = pa; 4938 PhysActor = pa;
4939
4457 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this); 4940 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
4458 } 4941 }
4459 4942
@@ -4462,14 +4945,21 @@ namespace OpenSim.Region.Framework.Scenes
4462 /// </summary> 4945 /// </summary>
4463 /// <remarks> 4946 /// <remarks>
4464 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4947 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4465 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4948 /// representation for collision detection.
4466 /// phantom.
4467 /// </remarks> 4949 /// </remarks>
4468 public void RemoveFromPhysics() 4950 public void RemoveFromPhysics()
4469 { 4951 {
4470 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this); 4952 PhysicsActor pa = PhysActor;
4471 if (ParentGroup.Scene.PhysicsScene != null) 4953 if (pa != null)
4472 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4954 {
4955 pa.OnCollisionUpdate -= PhysicsCollision;
4956 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4957 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4958
4959 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4960
4961 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
4962 }
4473 PhysActor = null; 4963 PhysActor = null;
4474 } 4964 }
4475 4965
@@ -4601,6 +5091,8 @@ namespace OpenSim.Region.Framework.Scenes
4601 { 5091 {
4602// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 5092// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4603 5093
5094 return;
5095
4604 if (ParentGroup.IsDeleted) 5096 if (ParentGroup.IsDeleted)
4605 return; 5097 return;
4606 5098
@@ -4724,6 +5216,44 @@ namespace OpenSim.Region.Framework.Scenes
4724 } 5216 }
4725 } 5217 }
4726 5218
5219
5220 private void UpdatePhysicsSubscribedEvents()
5221 {
5222 PhysicsActor pa = PhysActor;
5223 if (pa == null)
5224 return;
5225
5226 pa.OnCollisionUpdate -= PhysicsCollision;
5227
5228 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
5229
5230 scriptEvents CombinedEvents = AggregateScriptEvents;
5231
5232 // merge with root part
5233 if (ParentGroup != null && ParentGroup.RootPart != null)
5234 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
5235
5236 // submit to this part case
5237 if (VolumeDetectActive)
5238 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
5239 else if ((Flags & PrimFlags.Phantom) != 0)
5240 CombinedEvents &= PhyscicsPhantonSubsEvents;
5241 else
5242 CombinedEvents &= PhysicsNeededSubsEvents;
5243
5244 if (hassound || CombinedEvents != 0)
5245 {
5246 // subscribe to physics updates.
5247 pa.OnCollisionUpdate += PhysicsCollision;
5248 pa.SubscribeEvents(50); // 20 reports per second
5249 }
5250 else
5251 {
5252 pa.UnSubscribeEvents();
5253 }
5254 }
5255
5256
4727 public void aggregateScriptEvents() 5257 public void aggregateScriptEvents()
4728 { 5258 {
4729 if (ParentGroup == null || ParentGroup.RootPart == null) 5259 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4760,8 +5290,32 @@ namespace OpenSim.Region.Framework.Scenes
4760 { 5290 {
4761 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5291 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4762 } 5292 }
4763 5293/*
4764 SubscribeForCollisionEvents(); 5294 PhysicsActor pa = PhysActor;
5295 if (pa != null)
5296 {
5297 if (
5298// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
5299// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
5300// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
5301// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
5302// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
5303// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
5304 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
5305 )
5306 {
5307 // subscribe to physics updates.
5308 pa.OnCollisionUpdate += PhysicsCollision;
5309 pa.SubscribeEvents(1000);
5310 }
5311 else
5312 {
5313 pa.UnSubscribeEvents();
5314 pa.OnCollisionUpdate -= PhysicsCollision;
5315 }
5316 }
5317 */
5318 UpdatePhysicsSubscribedEvents();
4765 5319
4766 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5320 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4767 //{ 5321 //{
@@ -4970,6 +5524,18 @@ namespace OpenSim.Region.Framework.Scenes
4970 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5524 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4971 } 5525 }
4972 5526
5527 public void ResetOwnerChangeFlag()
5528 {
5529 List<UUID> inv = Inventory.GetInventoryList();
5530
5531 foreach (UUID itemID in inv)
5532 {
5533 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5534 item.OwnerChanged = false;
5535 Inventory.UpdateInventoryItem(item, false, false);
5536 }
5537 }
5538
4973 /// <summary> 5539 /// <summary>
4974 /// Record an avatar sitting on this part. 5540 /// Record an avatar sitting on this part.
4975 /// </summary> 5541 /// </summary>
@@ -4990,7 +5556,8 @@ namespace OpenSim.Region.Framework.Scenes
4990 5556
4991 if (m_sittingAvatars.Add(sp)) 5557 if (m_sittingAvatars.Add(sp))
4992 { 5558 {
4993 ParentGroup.m_sittingAvatars.Add(sp); 5559 if(!ParentGroup.m_sittingAvatars.Contains(sp))
5560 ParentGroup.m_sittingAvatars.Add(sp);
4994 5561
4995 return true; 5562 return true;
4996 } 5563 }
@@ -5063,4 +5630,4 @@ namespace OpenSim.Region.Framework.Scenes
5063 } 5630 }
5064 } 5631 }
5065 } 5632 }
5066} \ No newline at end of file 5633}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index ec39726..5811ed9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -46,9 +46,12 @@ namespace OpenSim.Region.Framework.Scenes
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 string m_inventoryFileName = String.Empty;
50 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
51 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52 private object m_inventoryFileLock = new object();
53
54 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
52 55
53 /// <value> 56 /// <value>
54 /// The part to which the inventory belongs. 57 /// The part to which the inventory belongs.
@@ -85,7 +88,9 @@ namespace OpenSim.Region.Framework.Scenes
85 /// </value> 88 /// </value>
86 protected internal TaskInventoryDictionary Items 89 protected internal TaskInventoryDictionary Items
87 { 90 {
88 get { return m_items; } 91 get {
92 return m_items;
93 }
89 set 94 set
90 { 95 {
91 m_items = value; 96 m_items = value;
@@ -134,38 +139,45 @@ namespace OpenSim.Region.Framework.Scenes
134 public void ResetInventoryIDs() 139 public void ResetInventoryIDs()
135 { 140 {
136 if (null == m_part) 141 if (null == m_part)
137 return; 142 m_items.LockItemsForWrite(true);
138 143
139 lock (m_items) 144 if (Items.Count == 0)
140 { 145 {
141 if (0 == m_items.Count) 146 m_items.LockItemsForWrite(false);
142 return; 147 return;
148 }
143 149
144 IList<TaskInventoryItem> items = GetInventoryItems(); 150 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
145 m_items.Clear(); 151 Items.Clear();
146 152
147 foreach (TaskInventoryItem item in items) 153 foreach (TaskInventoryItem item in items)
148 { 154 {
149 item.ResetIDs(m_part.UUID); 155 item.ResetIDs(m_part.UUID);
150 m_items.Add(item.ItemID, item); 156 Items.Add(item.ItemID, item);
151 }
152 } 157 }
158 m_items.LockItemsForWrite(false);
153 } 159 }
154 160
155 public void ResetObjectID() 161 public void ResetObjectID()
156 { 162 {
157 lock (Items) 163 m_items.LockItemsForWrite(true);
164
165 if (Items.Count == 0)
158 { 166 {
159 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 167 m_items.LockItemsForWrite(false);
160 Items.Clear(); 168 return;
161
162 foreach (TaskInventoryItem item in items)
163 {
164 item.ParentPartID = m_part.UUID;
165 item.ParentID = m_part.UUID;
166 Items.Add(item.ItemID, item);
167 }
168 } 169 }
170
171 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
172 Items.Clear();
173
174 foreach (TaskInventoryItem item in items)
175 {
176 item.ParentPartID = m_part.UUID;
177 item.ParentID = m_part.UUID;
178 Items.Add(item.ItemID, item);
179 }
180 m_items.LockItemsForWrite(false);
169 } 181 }
170 182
171 /// <summary> 183 /// <summary>
@@ -174,17 +186,14 @@ namespace OpenSim.Region.Framework.Scenes
174 /// <param name="ownerId"></param> 186 /// <param name="ownerId"></param>
175 public void ChangeInventoryOwner(UUID ownerId) 187 public void ChangeInventoryOwner(UUID ownerId)
176 { 188 {
177 lock (Items) 189 List<TaskInventoryItem> items = GetInventoryItems();
178 {
179 if (0 == Items.Count)
180 {
181 return;
182 }
183 }
184 190
191 if (items.Count == 0)
192 return;
193
194 m_items.LockItemsForWrite(true);
185 HasInventoryChanged = true; 195 HasInventoryChanged = true;
186 m_part.ParentGroup.HasGroupChanged = true; 196 m_part.ParentGroup.HasGroupChanged = true;
187 List<TaskInventoryItem> items = GetInventoryItems();
188 foreach (TaskInventoryItem item in items) 197 foreach (TaskInventoryItem item in items)
189 { 198 {
190 if (ownerId != item.OwnerID) 199 if (ownerId != item.OwnerID)
@@ -195,6 +204,7 @@ namespace OpenSim.Region.Framework.Scenes
195 item.PermsGranter = UUID.Zero; 204 item.PermsGranter = UUID.Zero;
196 item.OwnerChanged = true; 205 item.OwnerChanged = true;
197 } 206 }
207 m_items.LockItemsForWrite(false);
198 } 208 }
199 209
200 /// <summary> 210 /// <summary>
@@ -203,12 +213,11 @@ namespace OpenSim.Region.Framework.Scenes
203 /// <param name="groupID"></param> 213 /// <param name="groupID"></param>
204 public void ChangeInventoryGroup(UUID groupID) 214 public void ChangeInventoryGroup(UUID groupID)
205 { 215 {
206 lock (Items) 216 m_items.LockItemsForWrite(true);
217 if (0 == Items.Count)
207 { 218 {
208 if (0 == Items.Count) 219 m_items.LockItemsForWrite(false);
209 { 220 return;
210 return;
211 }
212 } 221 }
213 222
214 // Don't let this set the HasGroupChanged flag for attachments 223 // Don't let this set the HasGroupChanged flag for attachments
@@ -220,12 +229,15 @@ namespace OpenSim.Region.Framework.Scenes
220 m_part.ParentGroup.HasGroupChanged = true; 229 m_part.ParentGroup.HasGroupChanged = true;
221 } 230 }
222 231
223 List<TaskInventoryItem> items = GetInventoryItems(); 232 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
224 foreach (TaskInventoryItem item in items) 233 foreach (TaskInventoryItem item in items)
225 { 234 {
226 if (groupID != item.GroupID) 235 if (groupID != item.GroupID)
236 {
227 item.GroupID = groupID; 237 item.GroupID = groupID;
238 }
228 } 239 }
240 m_items.LockItemsForWrite(false);
229 } 241 }
230 242
231 private void QueryScriptStates() 243 private void QueryScriptStates()
@@ -233,15 +245,18 @@ namespace OpenSim.Region.Framework.Scenes
233 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) 245 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
234 return; 246 return;
235 247
236 lock (Items) 248 Items.LockItemsForRead(true);
249 foreach (TaskInventoryItem item in Items.Values)
237 { 250 {
238 foreach (TaskInventoryItem item in Items.Values) 251 if (item.InvType == (int)InventoryType.LSL)
239 { 252 {
240 bool running; 253 bool running;
241 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) 254 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running))
242 item.ScriptRunning = running; 255 item.ScriptRunning = running;
243 } 256 }
244 } 257 }
258
259 Items.LockItemsForRead(false);
245 } 260 }
246 261
247 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) 262 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
@@ -318,7 +333,10 @@ namespace OpenSim.Region.Framework.Scenes
318 { 333 {
319 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL); 334 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
320 foreach (TaskInventoryItem item in scripts) 335 foreach (TaskInventoryItem item in scripts)
336 {
321 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 337 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
338 m_part.RemoveScriptEvents(item.ItemID);
339 }
322 } 340 }
323 341
324 /// <summary> 342 /// <summary>
@@ -340,7 +358,10 @@ namespace OpenSim.Region.Framework.Scenes
340// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 358// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
341 359
342 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 360 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
361 {
362 StoreScriptError(item.ItemID, "no permission");
343 return false; 363 return false;
364 }
344 365
345 m_part.AddFlag(PrimFlags.Scripted); 366 m_part.AddFlag(PrimFlags.Scripted);
346 367
@@ -350,14 +371,13 @@ namespace OpenSim.Region.Framework.Scenes
350 if (stateSource == 2 && // Prim crossing 371 if (stateSource == 2 && // Prim crossing
351 m_part.ParentGroup.Scene.m_trustBinaries) 372 m_part.ParentGroup.Scene.m_trustBinaries)
352 { 373 {
353 lock (m_items) 374 m_items.LockItemsForWrite(true);
354 { 375 m_items[item.ItemID].PermsMask = 0;
355 m_items[item.ItemID].PermsMask = 0; 376 m_items[item.ItemID].PermsGranter = UUID.Zero;
356 m_items[item.ItemID].PermsGranter = UUID.Zero; 377 m_items.LockItemsForWrite(false);
357 }
358
359 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 378 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
360 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 379 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
380 StoreScriptErrors(item.ItemID, null);
361 m_part.ParentGroup.AddActiveScriptCount(1); 381 m_part.ParentGroup.AddActiveScriptCount(1);
362 m_part.ScheduleFullUpdate(); 382 m_part.ScheduleFullUpdate();
363 return true; 383 return true;
@@ -366,6 +386,8 @@ namespace OpenSim.Region.Framework.Scenes
366 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 386 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
367 if (null == asset) 387 if (null == asset)
368 { 388 {
389 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
390 StoreScriptError(item.ItemID, msg);
369 m_log.ErrorFormat( 391 m_log.ErrorFormat(
370 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 392 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
371 item.Name, item.ItemID, m_part.AbsolutePosition, 393 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -378,16 +400,18 @@ namespace OpenSim.Region.Framework.Scenes
378 if (m_part.ParentGroup.m_savedScriptState != null) 400 if (m_part.ParentGroup.m_savedScriptState != null)
379 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 401 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
380 402
381 lock (m_items) 403 m_items.LockItemsForWrite(true);
382 {
383 m_items[item.ItemID].OldItemID = item.OldItemID;
384 m_items[item.ItemID].PermsMask = 0;
385 m_items[item.ItemID].PermsGranter = UUID.Zero;
386 }
387 404
405 m_items[item.ItemID].OldItemID = item.OldItemID;
406 m_items[item.ItemID].PermsMask = 0;
407 m_items[item.ItemID].PermsGranter = UUID.Zero;
408
409 m_items.LockItemsForWrite(false);
410
388 string script = Utils.BytesToString(asset.Data); 411 string script = Utils.BytesToString(asset.Data);
389 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 412 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
390 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 413 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
414 StoreScriptErrors(item.ItemID, null);
391 if (!item.ScriptRunning) 415 if (!item.ScriptRunning)
392 m_part.ParentGroup.Scene.EventManager.TriggerStopScript( 416 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
393 m_part.LocalId, item.ItemID); 417 m_part.LocalId, item.ItemID);
@@ -466,22 +490,138 @@ namespace OpenSim.Region.Framework.Scenes
466 return stateID; 490 return stateID;
467 } 491 }
468 492
493 /// <summary>
494 /// Start a script which is in this prim's inventory.
495 /// Some processing may occur in the background, but this routine returns asap.
496 /// </summary>
497 /// <param name="itemId">
498 /// A <see cref="UUID"/>
499 /// </param>
469 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 500 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
470 { 501 {
471 TaskInventoryItem item = GetInventoryItem(itemId); 502 lock (m_scriptErrors)
472 if (item != null) 503 {
504 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
505 m_scriptErrors.Remove(itemId);
506 }
507 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
508 return true;
509 }
510
511 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
512 {
513 m_items.LockItemsForRead(true);
514
515 if (m_items.ContainsKey(itemId))
473 { 516 {
474 return CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 517 TaskInventoryItem it = m_items[itemId];
518 m_items.LockItemsForRead(false);
519
520 CreateScriptInstance(it, startParam, postOnRez, engine, stateSource);
475 } 521 }
476 else 522 else
477 { 523 {
478 m_log.ErrorFormat( 524 m_items.LockItemsForRead(false);
479 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 525 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
480 itemId, m_part.Name, m_part.UUID,
481 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 526 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
527 StoreScriptError(itemId, msg);
528 m_log.ErrorFormat(
529 "[PRIM INVENTORY]: " +
530 "Couldn't start script with ID {0} since it {1}", itemId, msg);
531 }
532 }
482 533
483 return false; 534 /// <summary>
535 /// Start a script which is in this prim's inventory and return any compilation error messages.
536 /// </summary>
537 /// <param name="itemId">
538 /// A <see cref="UUID"/>
539 /// </param>
540 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
541 {
542 ArrayList errors;
543
544 // Indicate to CreateScriptInstanceInternal() we want it to
545 // post any compilation/loading error messages
546 lock (m_scriptErrors)
547 {
548 m_scriptErrors[itemId] = null;
484 } 549 }
550
551 // Perform compilation/loading
552 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
553
554 // Wait for and retrieve any errors
555 lock (m_scriptErrors)
556 {
557 while ((errors = m_scriptErrors[itemId]) == null)
558 {
559 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
560 {
561 m_log.ErrorFormat(
562 "[PRIM INVENTORY]: " +
563 "timedout waiting for script {0} errors", itemId);
564 errors = m_scriptErrors[itemId];
565 if (errors == null)
566 {
567 errors = new ArrayList(1);
568 errors.Add("timedout waiting for errors");
569 }
570 break;
571 }
572 }
573 m_scriptErrors.Remove(itemId);
574 }
575 return errors;
576 }
577
578 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
579 private void StoreScriptErrors(UUID itemId, ArrayList errors)
580 {
581 lock (m_scriptErrors)
582 {
583 // If compilation/loading initiated via CreateScriptInstance(),
584 // it does not want the errors, so just get out
585 if (!m_scriptErrors.ContainsKey(itemId))
586 {
587 return;
588 }
589
590 // Initiated via CreateScriptInstanceEr(), if we know what the
591 // errors are, save them and wake CreateScriptInstanceEr().
592 if (errors != null)
593 {
594 m_scriptErrors[itemId] = errors;
595 System.Threading.Monitor.PulseAll(m_scriptErrors);
596 return;
597 }
598 }
599
600 // Initiated via CreateScriptInstanceEr() but we don't know what
601 // the errors are yet, so retrieve them from the script engine.
602 // This may involve some waiting internal to GetScriptErrors().
603 errors = GetScriptErrors(itemId);
604
605 // Get a default non-null value to indicate success.
606 if (errors == null)
607 {
608 errors = new ArrayList();
609 }
610
611 // Post to CreateScriptInstanceEr() and wake it up
612 lock (m_scriptErrors)
613 {
614 m_scriptErrors[itemId] = errors;
615 System.Threading.Monitor.PulseAll(m_scriptErrors);
616 }
617 }
618
619 // Like StoreScriptErrors(), but just posts a single string message
620 private void StoreScriptError(UUID itemId, string message)
621 {
622 ArrayList errors = new ArrayList(1);
623 errors.Add(message);
624 StoreScriptErrors(itemId, errors);
485 } 625 }
486 626
487 /// <summary> 627 /// <summary>
@@ -494,15 +634,7 @@ namespace OpenSim.Region.Framework.Scenes
494 /// </param> 634 /// </param>
495 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 635 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
496 { 636 {
497 bool scriptPresent = false; 637 if (m_items.ContainsKey(itemId))
498
499 lock (m_items)
500 {
501 if (m_items.ContainsKey(itemId))
502 scriptPresent = true;
503 }
504
505 if (scriptPresent)
506 { 638 {
507 if (!sceneObjectBeingDeleted) 639 if (!sceneObjectBeingDeleted)
508 m_part.RemoveScriptEvents(itemId); 640 m_part.RemoveScriptEvents(itemId);
@@ -573,14 +705,16 @@ namespace OpenSim.Region.Framework.Scenes
573 /// <returns></returns> 705 /// <returns></returns>
574 private bool InventoryContainsName(string name) 706 private bool InventoryContainsName(string name)
575 { 707 {
576 lock (m_items) 708 m_items.LockItemsForRead(true);
709 foreach (TaskInventoryItem item in m_items.Values)
577 { 710 {
578 foreach (TaskInventoryItem item in m_items.Values) 711 if (item.Name == name)
579 { 712 {
580 if (item.Name == name) 713 m_items.LockItemsForRead(false);
581 return true; 714 return true;
582 } 715 }
583 } 716 }
717 m_items.LockItemsForRead(false);
584 return false; 718 return false;
585 } 719 }
586 720
@@ -622,8 +756,9 @@ namespace OpenSim.Region.Framework.Scenes
622 /// <param name="item"></param> 756 /// <param name="item"></param>
623 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 757 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
624 { 758 {
625 List<TaskInventoryItem> il = GetInventoryItems(); 759 m_items.LockItemsForRead(true);
626 760 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
761 m_items.LockItemsForRead(false);
627 foreach (TaskInventoryItem i in il) 762 foreach (TaskInventoryItem i in il)
628 { 763 {
629 if (i.Name == item.Name) 764 if (i.Name == item.Name)
@@ -661,14 +796,14 @@ namespace OpenSim.Region.Framework.Scenes
661 item.Name = name; 796 item.Name = name;
662 item.GroupID = m_part.GroupID; 797 item.GroupID = m_part.GroupID;
663 798
664 lock (m_items) 799 m_items.LockItemsForWrite(true);
665 m_items.Add(item.ItemID, item); 800 m_items.Add(item.ItemID, item);
666 801 m_items.LockItemsForWrite(false);
667 if (allowedDrop) 802 if (allowedDrop)
668 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 803 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
669 else 804 else
670 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 805 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
671 806
672 m_inventorySerial++; 807 m_inventorySerial++;
673 //m_inventorySerial += 2; 808 //m_inventorySerial += 2;
674 HasInventoryChanged = true; 809 HasInventoryChanged = true;
@@ -684,15 +819,15 @@ namespace OpenSim.Region.Framework.Scenes
684 /// <param name="items"></param> 819 /// <param name="items"></param>
685 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 820 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
686 { 821 {
687 lock (m_items) 822 m_items.LockItemsForWrite(true);
823 foreach (TaskInventoryItem item in items)
688 { 824 {
689 foreach (TaskInventoryItem item in items) 825 m_items.Add(item.ItemID, item);
690 { 826// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
691 m_items.Add(item.ItemID, item);
692// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
693 }
694 m_inventorySerial++;
695 } 827 }
828 m_items.LockItemsForWrite(false);
829
830 m_inventorySerial++;
696 } 831 }
697 832
698 /// <summary> 833 /// <summary>
@@ -703,23 +838,24 @@ namespace OpenSim.Region.Framework.Scenes
703 public TaskInventoryItem GetInventoryItem(UUID itemId) 838 public TaskInventoryItem GetInventoryItem(UUID itemId)
704 { 839 {
705 TaskInventoryItem item; 840 TaskInventoryItem item;
706 841 m_items.LockItemsForRead(true);
707 lock (m_items) 842 m_items.TryGetValue(itemId, out item);
708 m_items.TryGetValue(itemId, out item); 843 m_items.LockItemsForRead(false);
709
710 return item; 844 return item;
711 } 845 }
712 846
713 public TaskInventoryItem GetInventoryItem(string name) 847 public TaskInventoryItem GetInventoryItem(string name)
714 { 848 {
715 lock (m_items) 849 m_items.LockItemsForRead(true);
850 foreach (TaskInventoryItem item in m_items.Values)
716 { 851 {
717 foreach (TaskInventoryItem item in m_items.Values) 852 if (item.Name == name)
718 { 853 {
719 if (item.Name == name) 854 m_items.LockItemsForRead(false);
720 return item; 855 return item;
721 } 856 }
722 } 857 }
858 m_items.LockItemsForRead(false);
723 859
724 return null; 860 return null;
725 } 861 }
@@ -728,19 +864,20 @@ namespace OpenSim.Region.Framework.Scenes
728 { 864 {
729 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 865 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
730 866
731 lock (m_items) 867 m_items.LockItemsForRead(true);
868
869 foreach (TaskInventoryItem item in m_items.Values)
732 { 870 {
733 foreach (TaskInventoryItem item in m_items.Values) 871 if (item.Name == name)
734 { 872 items.Add(item);
735 if (item.Name == name)
736 items.Add(item);
737 }
738 } 873 }
739 874
875 m_items.LockItemsForRead(false);
876
740 return items; 877 return items;
741 } 878 }
742 879
743 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist) 880 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight)
744 { 881 {
745 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 882 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
746 883
@@ -751,18 +888,21 @@ namespace OpenSim.Region.Framework.Scenes
751 item.AssetID, item.Name, m_part.Name); 888 item.AssetID, item.Name, m_part.Name);
752 objlist = null; 889 objlist = null;
753 veclist = null; 890 veclist = null;
891 bbox = Vector3.Zero;
892 offsetHeight = 0;
754 return false; 893 return false;
755 } 894 }
756 895
757 Vector3 bbox; 896 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
758 float offsetHeight;
759
760 m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
761 897
762 for (int i = 0; i < objlist.Count; i++) 898 for (int i = 0; i < objlist.Count; i++)
763 { 899 {
764 SceneObjectGroup group = objlist[i]; 900 SceneObjectGroup group = objlist[i];
765 901/*
902 group.RootPart.AttachPoint = group.RootPart.Shape.State;
903 group.RootPart.AttachedPos = group.AbsolutePosition;
904 group.RootPart.AttachRotation = group.GroupRotation;
905*/
766 group.ResetIDs(); 906 group.ResetIDs();
767 907
768 SceneObjectPart rootPart = group.GetPart(group.UUID); 908 SceneObjectPart rootPart = group.GetPart(group.UUID);
@@ -771,12 +911,14 @@ namespace OpenSim.Region.Framework.Scenes
771 // in the serialization, transfer the correct name from the inventory to the 911 // in the serialization, transfer the correct name from the inventory to the
772 // object itself before we rez. 912 // object itself before we rez.
773 // Only do these for the first object if we are rezzing a coalescence. 913 // Only do these for the first object if we are rezzing a coalescence.
774 if (i == 0) 914 // nahh dont mess with coalescence objects,
915 // the name in inventory can be change for inventory purpuses only
916 if (objlist.Count == 1)
775 { 917 {
776 rootPart.Name = item.Name; 918 rootPart.Name = item.Name;
777 rootPart.Description = item.Description; 919 rootPart.Description = item.Description;
778 } 920 }
779 921/* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed
780 group.SetGroup(m_part.GroupID, null); 922 group.SetGroup(m_part.GroupID, null);
781 923
782 foreach (SceneObjectPart part in group.Parts) 924 foreach (SceneObjectPart part in group.Parts)
@@ -792,7 +934,49 @@ namespace OpenSim.Region.Framework.Scenes
792 934
793 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene); 935 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
794 } 936 }
937*/
938// old code start
939 SceneObjectPart[] partList = group.Parts;
940
941 group.SetGroup(m_part.GroupID, null);
942
943 // TODO: Remove magic number badness
944 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
945 {
946 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
947 {
948 foreach (SceneObjectPart part in partList)
949 {
950 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
951 part.EveryoneMask = item.EveryonePermissions;
952 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
953 part.NextOwnerMask = item.NextPermissions;
954 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
955 part.GroupMask = item.GroupPermissions;
956 }
957
958 group.ApplyNextOwnerPermissions();
959 }
960 }
961
962 foreach (SceneObjectPart part in partList)
963 {
964 // TODO: Remove magic number badness
965 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
966 {
967 part.LastOwnerID = part.OwnerID;
968 part.OwnerID = item.OwnerID;
969 part.Inventory.ChangeInventoryOwner(item.OwnerID);
970 }
795 971
972 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
973 part.EveryoneMask = item.EveryonePermissions;
974 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
975 part.NextOwnerMask = item.NextPermissions;
976 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
977 part.GroupMask = item.GroupPermissions;
978 }
979// old code end
796 rootPart.TrimPermissions(); 980 rootPart.TrimPermissions();
797 } 981 }
798 982
@@ -817,8 +1001,9 @@ namespace OpenSim.Region.Framework.Scenes
817 1001
818 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 1002 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
819 { 1003 {
820 TaskInventoryItem it = GetInventoryItem(item.ItemID); 1004 m_items.LockItemsForWrite(true);
821 if (it != null) 1005
1006 if (m_items.ContainsKey(item.ItemID))
822 { 1007 {
823// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 1008// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
824 1009
@@ -831,14 +1016,10 @@ namespace OpenSim.Region.Framework.Scenes
831 item.GroupID = m_part.GroupID; 1016 item.GroupID = m_part.GroupID;
832 1017
833 if (item.AssetID == UUID.Zero) 1018 if (item.AssetID == UUID.Zero)
834 item.AssetID = it.AssetID; 1019 item.AssetID = m_items[item.ItemID].AssetID;
835 1020
836 lock (m_items) 1021 m_items[item.ItemID] = item;
837 { 1022 m_inventorySerial++;
838 m_items[item.ItemID] = item;
839 m_inventorySerial++;
840 }
841
842 if (fireScriptEvents) 1023 if (fireScriptEvents)
843 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 1024 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
844 1025
@@ -847,7 +1028,7 @@ namespace OpenSim.Region.Framework.Scenes
847 HasInventoryChanged = true; 1028 HasInventoryChanged = true;
848 m_part.ParentGroup.HasGroupChanged = true; 1029 m_part.ParentGroup.HasGroupChanged = true;
849 } 1030 }
850 1031 m_items.LockItemsForWrite(false);
851 return true; 1032 return true;
852 } 1033 }
853 else 1034 else
@@ -858,8 +1039,9 @@ namespace OpenSim.Region.Framework.Scenes
858 item.ItemID, m_part.Name, m_part.UUID, 1039 item.ItemID, m_part.Name, m_part.UUID,
859 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 1040 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
860 } 1041 }
861 return false; 1042 m_items.LockItemsForWrite(false);
862 1043
1044 return false;
863 } 1045 }
864 1046
865 /// <summary> 1047 /// <summary>
@@ -870,160 +1052,182 @@ namespace OpenSim.Region.Framework.Scenes
870 /// in this prim's inventory.</returns> 1052 /// in this prim's inventory.</returns>
871 public int RemoveInventoryItem(UUID itemID) 1053 public int RemoveInventoryItem(UUID itemID)
872 { 1054 {
873 TaskInventoryItem item = GetInventoryItem(itemID); 1055 m_items.LockItemsForRead(true);
874 if (item != null) 1056
1057 if (m_items.ContainsKey(itemID))
875 { 1058 {
876 int type = m_items[itemID].InvType; 1059 int type = m_items[itemID].InvType;
1060 m_items.LockItemsForRead(false);
877 if (type == 10) // Script 1061 if (type == 10) // Script
878 { 1062 {
879 // route it through here, to handle script cleanup tasks 1063 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
880 RemoveScriptInstance(itemID, false);
881 } 1064 }
1065 m_items.LockItemsForWrite(true);
882 m_items.Remove(itemID); 1066 m_items.Remove(itemID);
1067 m_items.LockItemsForWrite(false);
883 m_inventorySerial++; 1068 m_inventorySerial++;
884 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 1069 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
885 1070
886 HasInventoryChanged = true; 1071 HasInventoryChanged = true;
887 m_part.ParentGroup.HasGroupChanged = true; 1072 m_part.ParentGroup.HasGroupChanged = true;
888 1073
889 if (!ContainsScripts()) 1074 int scriptcount = 0;
1075 m_items.LockItemsForRead(true);
1076 foreach (TaskInventoryItem item in m_items.Values)
1077 {
1078 if (item.Type == 10)
1079 {
1080 scriptcount++;
1081 }
1082 }
1083 m_items.LockItemsForRead(false);
1084
1085
1086 if (scriptcount <= 0)
1087 {
890 m_part.RemFlag(PrimFlags.Scripted); 1088 m_part.RemFlag(PrimFlags.Scripted);
1089 }
891 1090
892 m_part.ScheduleFullUpdate(); 1091 m_part.ScheduleFullUpdate();
893 1092
894 return type; 1093 return type;
895
896 } 1094 }
897 else 1095 else
898 { 1096 {
1097 m_items.LockItemsForRead(false);
899 m_log.ErrorFormat( 1098 m_log.ErrorFormat(
900 "[PRIM INVENTORY]: " + 1099 "[PRIM INVENTORY]: " +
901 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 1100 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
902 itemID, m_part.Name, m_part.UUID, 1101 itemID, m_part.Name, m_part.UUID);
903 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
904 } 1102 }
905 1103
906 return -1; 1104 return -1;
907 } 1105 }
908 1106
909 private bool CreateInventoryFile() 1107
1108 /// <summary>
1109 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1110 /// </summary>
1111 /// <param name="xferManager"></param>
1112 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
910 { 1113 {
911// m_log.DebugFormat(
912// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
913// m_part.Name, m_part.UUID, m_part.LocalId, m_inventorySerial);
914 1114
915 if (m_inventoryFileName == String.Empty || 1115 lock (m_inventoryFileLock)
916 m_inventoryFileNameSerial < m_inventorySerial)
917 { 1116 {
918 // Something changed, we need to create a new file 1117 string filename = "inventory_" + UUID.Random().ToString() + ".tmp";
919 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
920 m_inventoryFileNameSerial = m_inventorySerial;
921
922 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
923 1118
924 lock (m_items) 1119 bool changed = false;
1120 if (m_inventoryFileNameSerial < m_inventorySerial)
925 { 1121 {
926 foreach (TaskInventoryItem item in m_items.Values) 1122 m_inventoryFileNameSerial = m_inventorySerial;
927 { 1123 changed = true;
928// m_log.DebugFormat( 1124 }
929// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}",
930// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
931
932 UUID ownerID = item.OwnerID;
933 uint everyoneMask = 0;
934 uint baseMask = item.BasePermissions;
935 uint ownerMask = item.CurrentPermissions;
936 uint groupMask = item.GroupPermissions;
937 1125
938 invString.AddItemStart(); 1126 if (m_inventoryFileData.Length < 2)
939 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 1127 changed = true;
940 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
941 1128
942 invString.AddPermissionsStart(); 1129 bool includeAssets = false;
1130 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1131 includeAssets = true;
943 1132
944 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1133 if (m_inventoryPrivileged != includeAssets)
945 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1134 changed = true;
946 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
947 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
948 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
949 1135
950 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
951 invString.AddNameValueLine("owner_id", ownerID.ToString());
952 1136
953 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1137 Items.LockItemsForRead(true);
954 1138
955 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1139 if (m_inventorySerial == 0) // No inventory
956 invString.AddSectionEnd(); 1140 {
1141 Items.LockItemsForRead(false);
1142 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1143
1144 return;
1145 }
957 1146
958 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1147 if (m_items.Count == 0) // No inventory
959 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); 1148 {
960 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType)); 1149 Items.LockItemsForRead(false);
961 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 1150 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1151 return;
1152 }
962 1153
963 invString.AddSaleStart(); 1154 if (!changed)
964 invString.AddNameValueLine("sale_type", "not"); 1155 {
965 invString.AddNameValueLine("sale_price", "0"); 1156 Items.LockItemsForRead(false);
966 invString.AddSectionEnd();
967 1157
968 invString.AddNameValueLine("name", item.Name + "|"); 1158 xferManager.AddNewFile(filename,
969 invString.AddNameValueLine("desc", item.Description + "|"); 1159 m_inventoryFileData);
1160 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1161 Util.StringToBytes256(filename));
970 1162
971 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1163 return;
972 invString.AddSectionEnd();
973 }
974 } 1164 }
975 1165
976 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1166 m_inventoryPrivileged = includeAssets;
977 1167
978 return true; 1168 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
979 }
980
981 // No need to recreate, the existing file is fine
982 return false;
983 }
984 1169
985 /// <summary> 1170 foreach (TaskInventoryItem item in m_items.Values)
986 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
987 /// </summary>
988 /// <param name="xferManager"></param>
989 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
990 {
991 lock (m_items)
992 {
993 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
994 // a new script if any previous deletion has left the prim inventory empty.
995 if (m_items.Count == 0) // No inventory
996 { 1171 {
997// m_log.DebugFormat( 1172 UUID ownerID = item.OwnerID;
998// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items", 1173 uint everyoneMask = 0;
999// m_part.Name, m_part.LocalId, m_part.UUID, client.Name); 1174 uint baseMask = item.BasePermissions;
1175 uint ownerMask = item.CurrentPermissions;
1176 uint groupMask = item.GroupPermissions;
1000 1177
1001 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1178 invString.AddItemStart();
1002 return; 1179 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1180 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1181
1182 invString.AddPermissionsStart();
1183
1184 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1185 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1186 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1187 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1188 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1189
1190 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1191 invString.AddNameValueLine("owner_id", ownerID.ToString());
1192
1193 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1194
1195 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1196 invString.AddSectionEnd();
1197
1198 if (includeAssets)
1199 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1200 else
1201 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1202 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1203 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1204 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1205
1206 invString.AddSaleStart();
1207 invString.AddNameValueLine("sale_type", "not");
1208 invString.AddNameValueLine("sale_price", "0");
1209 invString.AddSectionEnd();
1210
1211 invString.AddNameValueLine("name", item.Name + "|");
1212 invString.AddNameValueLine("desc", item.Description + "|");
1213
1214 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1215 invString.AddSectionEnd();
1003 } 1216 }
1004 1217
1005 CreateInventoryFile(); 1218 Items.LockItemsForRead(false);
1006 1219
1007 // In principle, we should only do the rest if the inventory changed; 1220 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
1008 // by sending m_inventorySerial to the client, it ought to know 1221
1009 // that nothing changed and that it doesn't need to request the file.
1010 // Unfortunately, it doesn't look like the client optimizes this;
1011 // the client seems to always come back and request the Xfer,
1012 // no matter what value m_inventorySerial has.
1013 // FIXME: Could probably be > 0 here rather than > 2
1014 if (m_inventoryFileData.Length > 2) 1222 if (m_inventoryFileData.Length > 2)
1015 { 1223 {
1016 // Add the file for Xfer 1224 xferManager.AddNewFile(filename, m_inventoryFileData);
1017 // m_log.DebugFormat( 1225 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1018 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}", 1226 Util.StringToBytes256(filename));
1019 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId); 1227 return;
1020
1021 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1022 } 1228 }
1023 1229
1024 // Tell the client we're ready to Xfer the file 1230 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1025 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1026 Util.StringToBytes256(m_inventoryFileName));
1027 } 1231 }
1028 } 1232 }
1029 1233
@@ -1033,13 +1237,26 @@ namespace OpenSim.Region.Framework.Scenes
1033 /// <param name="datastore"></param> 1237 /// <param name="datastore"></param>
1034 public void ProcessInventoryBackup(ISimulationDataService datastore) 1238 public void ProcessInventoryBackup(ISimulationDataService datastore)
1035 { 1239 {
1036 if (HasInventoryChanged) 1240// Removed this because linking will cause an immediate delete of the new
1037 { 1241// child prim from the database and the subsequent storing of the prim sees
1242// the inventory of it as unchanged and doesn't store it at all. The overhead
1243// of storing prim inventory needlessly is much less than the aggravation
1244// of prim inventory loss.
1245// if (HasInventoryChanged)
1246// {
1247 Items.LockItemsForRead(true);
1248 try
1249 {
1250 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1251 }
1252 catch {}
1253
1038 HasInventoryChanged = false; 1254 HasInventoryChanged = false;
1039 List<TaskInventoryItem> items = GetInventoryItems();
1040 datastore.StorePrimInventory(m_part.UUID, items);
1041 1255
1042 } 1256 Items.LockItemsForRead(false);
1257
1258
1259// }
1043 } 1260 }
1044 1261
1045 public class InventoryStringBuilder 1262 public class InventoryStringBuilder
@@ -1105,65 +1322,63 @@ namespace OpenSim.Region.Framework.Scenes
1105 { 1322 {
1106 uint mask=0x7fffffff; 1323 uint mask=0x7fffffff;
1107 1324
1108 lock (m_items) 1325 foreach (TaskInventoryItem item in m_items.Values)
1109 { 1326 {
1110 foreach (TaskInventoryItem item in m_items.Values) 1327 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1328 mask &= ~((uint)PermissionMask.Copy >> 13);
1329 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1330 mask &= ~((uint)PermissionMask.Transfer >> 13);
1331 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1332 mask &= ~((uint)PermissionMask.Modify >> 13);
1333
1334 if (item.InvType == (int)InventoryType.Object)
1111 { 1335 {
1112 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1336 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1113 mask &= ~((uint)PermissionMask.Copy >> 13); 1337 mask &= ~((uint)PermissionMask.Copy >> 13);
1114 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1338 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1115 mask &= ~((uint)PermissionMask.Transfer >> 13); 1339 mask &= ~((uint)PermissionMask.Transfer >> 13);
1116 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1340 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1117 mask &= ~((uint)PermissionMask.Modify >> 13); 1341 mask &= ~((uint)PermissionMask.Modify >> 13);
1118
1119 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1120 mask &= ~(uint)PermissionMask.Copy;
1121 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1122 mask &= ~(uint)PermissionMask.Transfer;
1123 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1124 mask &= ~(uint)PermissionMask.Modify;
1125 } 1342 }
1343
1344 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1345 mask &= ~(uint)PermissionMask.Copy;
1346 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1347 mask &= ~(uint)PermissionMask.Transfer;
1348 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1349 mask &= ~(uint)PermissionMask.Modify;
1126 } 1350 }
1127
1128 return mask; 1351 return mask;
1129 } 1352 }
1130 1353
1131 public void ApplyNextOwnerPermissions() 1354 public void ApplyNextOwnerPermissions()
1132 { 1355 {
1133 lock (m_items) 1356 foreach (TaskInventoryItem item in m_items.Values)
1134 { 1357 {
1135 foreach (TaskInventoryItem item in m_items.Values) 1358 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1136 { 1359 {
1137// m_log.DebugFormat ( 1360 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1138// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", 1361 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1139// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); 1362 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1140 1363 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1141 if (item.InvType == (int)InventoryType.Object) 1364 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1142 { 1365 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1143 uint perms = item.CurrentPermissions;
1144 PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
1145 item.CurrentPermissions = perms;
1146 }
1147
1148 item.CurrentPermissions &= item.NextPermissions;
1149 item.BasePermissions &= item.NextPermissions;
1150 item.EveryonePermissions &= item.NextPermissions;
1151 item.OwnerChanged = true;
1152 item.PermsMask = 0;
1153 item.PermsGranter = UUID.Zero;
1154 } 1366 }
1367 item.CurrentPermissions &= item.NextPermissions;
1368 item.BasePermissions &= item.NextPermissions;
1369 item.EveryonePermissions &= item.NextPermissions;
1370 item.OwnerChanged = true;
1371 item.PermsMask = 0;
1372 item.PermsGranter = UUID.Zero;
1155 } 1373 }
1156 } 1374 }
1157 1375
1158 public void ApplyGodPermissions(uint perms) 1376 public void ApplyGodPermissions(uint perms)
1159 { 1377 {
1160 lock (m_items) 1378 foreach (TaskInventoryItem item in m_items.Values)
1161 { 1379 {
1162 foreach (TaskInventoryItem item in m_items.Values) 1380 item.CurrentPermissions = perms;
1163 { 1381 item.BasePermissions = perms;
1164 item.CurrentPermissions = perms;
1165 item.BasePermissions = perms;
1166 }
1167 } 1382 }
1168 1383
1169 m_inventorySerial++; 1384 m_inventorySerial++;
@@ -1176,14 +1391,11 @@ namespace OpenSim.Region.Framework.Scenes
1176 /// <returns></returns> 1391 /// <returns></returns>
1177 public bool ContainsScripts() 1392 public bool ContainsScripts()
1178 { 1393 {
1179 lock (m_items) 1394 foreach (TaskInventoryItem item in m_items.Values)
1180 { 1395 {
1181 foreach (TaskInventoryItem item in m_items.Values) 1396 if (item.InvType == (int)InventoryType.LSL)
1182 { 1397 {
1183 if (item.InvType == (int)InventoryType.LSL) 1398 return true;
1184 {
1185 return true;
1186 }
1187 } 1399 }
1188 } 1400 }
1189 1401
@@ -1197,17 +1409,15 @@ namespace OpenSim.Region.Framework.Scenes
1197 public int ScriptCount() 1409 public int ScriptCount()
1198 { 1410 {
1199 int count = 0; 1411 int count = 0;
1200 lock (m_items) 1412 Items.LockItemsForRead(true);
1413 foreach (TaskInventoryItem item in m_items.Values)
1201 { 1414 {
1202 foreach (TaskInventoryItem item in m_items.Values) 1415 if (item.InvType == (int)InventoryType.LSL)
1203 { 1416 {
1204 if (item.InvType == (int)InventoryType.LSL) 1417 count++;
1205 {
1206 count++;
1207 }
1208 } 1418 }
1209 } 1419 }
1210 1420 Items.LockItemsForRead(false);
1211 return count; 1421 return count;
1212 } 1422 }
1213 /// <summary> 1423 /// <summary>
@@ -1243,11 +1453,8 @@ namespace OpenSim.Region.Framework.Scenes
1243 { 1453 {
1244 List<UUID> ret = new List<UUID>(); 1454 List<UUID> ret = new List<UUID>();
1245 1455
1246 lock (m_items) 1456 foreach (TaskInventoryItem item in m_items.Values)
1247 { 1457 ret.Add(item.ItemID);
1248 foreach (TaskInventoryItem item in m_items.Values)
1249 ret.Add(item.ItemID);
1250 }
1251 1458
1252 return ret; 1459 return ret;
1253 } 1460 }
@@ -1256,8 +1463,9 @@ namespace OpenSim.Region.Framework.Scenes
1256 { 1463 {
1257 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1464 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1258 1465
1259 lock (m_items) 1466 Items.LockItemsForRead(true);
1260 ret = new List<TaskInventoryItem>(m_items.Values); 1467 ret = new List<TaskInventoryItem>(m_items.Values);
1468 Items.LockItemsForRead(false);
1261 1469
1262 return ret; 1470 return ret;
1263 } 1471 }
@@ -1266,18 +1474,24 @@ namespace OpenSim.Region.Framework.Scenes
1266 { 1474 {
1267 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1475 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1268 1476
1269 lock (m_items) 1477 Items.LockItemsForRead(true);
1270 { 1478
1271 foreach (TaskInventoryItem item in m_items.Values) 1479 foreach (TaskInventoryItem item in m_items.Values)
1272 if (item.InvType == (int)type) 1480 if (item.InvType == (int)type)
1273 ret.Add(item); 1481 ret.Add(item);
1274 } 1482
1483 Items.LockItemsForRead(false);
1275 1484
1276 return ret; 1485 return ret;
1277 } 1486 }
1278 1487
1279 public Dictionary<UUID, string> GetScriptStates() 1488 public Dictionary<UUID, string> GetScriptStates()
1280 { 1489 {
1490 return GetScriptStates(false);
1491 }
1492
1493 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1494 {
1281 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1495 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1282 1496
1283 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1497 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1303,14 +1517,21 @@ namespace OpenSim.Region.Framework.Scenes
1303 string n = e.GetXMLState(item.ItemID); 1517 string n = e.GetXMLState(item.ItemID);
1304 if (n != String.Empty) 1518 if (n != String.Empty)
1305 { 1519 {
1306 if (!ret.ContainsKey(item.ItemID)) 1520 if (oldIDs)
1307 ret[item.ItemID] = n; 1521 {
1522 if (!ret.ContainsKey(item.OldItemID))
1523 ret[item.OldItemID] = n;
1524 }
1525 else
1526 {
1527 if (!ret.ContainsKey(item.ItemID))
1528 ret[item.ItemID] = n;
1529 }
1308 break; 1530 break;
1309 } 1531 }
1310 } 1532 }
1311 } 1533 }
1312 } 1534 }
1313
1314 return ret; 1535 return ret;
1315 } 1536 }
1316 1537
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1fddd91..c3deeaf 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -90,7 +90,17 @@ namespace OpenSim.Region.Framework.Scenes
90 m_scene.EventManager.TriggerScenePresenceUpdated(this); 90 m_scene.EventManager.TriggerScenePresenceUpdated(this);
91 } 91 }
92 92
93 public PresenceType PresenceType { get; private set; } 93 public bool isNPC { get; private set; }
94
95 private PresenceType m_presenceType;
96 public PresenceType PresenceType {
97 get {return m_presenceType;}
98 private set
99 {
100 m_presenceType = value;
101 isNPC = (m_presenceType == PresenceType.Npc);
102 }
103 }
94 104
95 private ScenePresenceStateMachine m_stateMachine; 105 private ScenePresenceStateMachine m_stateMachine;
96 106
@@ -142,13 +152,100 @@ namespace OpenSim.Region.Framework.Scenes
142 /// </summary> 152 /// </summary>
143 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; 153 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f;
144 154
145 public UUID currentParcelUUID = UUID.Zero; 155 private UUID m_previusParcelUUID = UUID.Zero;
156 private UUID m_currentParcelUUID = UUID.Zero;
157 private bool m_previusParcelHide = false;
158 private bool m_currentParcelHide = false;
159 private object parcelLock = new Object();
146 160
161 public UUID currentParcelUUID
162 {
163 get { return m_currentParcelUUID; }
164 set
165 {
166 lock (parcelLock)
167 {
168 bool oldhide = m_currentParcelHide;
169 bool checksame = true;
170 if (value != m_currentParcelUUID)
171 {
172 m_previusParcelHide = m_currentParcelHide;
173 m_previusParcelUUID = m_currentParcelUUID;
174 checksame = false;
175 }
176 m_currentParcelUUID = value;
177 m_currentParcelHide = false;
178
179 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
180 if (land != null && !land.LandData.SeeAVs)
181 m_currentParcelHide = true;
182
183 if (m_previusParcelUUID != UUID.Zero || checksame)
184 ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
185 }
186 }
187 }
188
189 public void sitSOGmoved()
190 {
191 if (IsDeleted || !IsSatOnObject)
192 //what me? nahh
193 return;
194 if (IsInTransit)
195 return;
196
197 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
198 if (land == null)
199 return; //??
200 UUID parcelID = land.LandData.GlobalID;
201 if (m_currentParcelUUID != parcelID)
202 currentParcelUUID = parcelID;
203 }
204
205
206 public bool ParcelAllowThisAvatarSounds
207 {
208 get
209 {
210 try
211 {
212 lock (parcelLock)
213 {
214 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
215 if (land == null)
216 return true;
217 if (land.LandData.AnyAVSounds)
218 return true;
219 if (!land.LandData.GroupAVSounds)
220 return false;
221 return land.LandData.GroupID == ControllingClient.ActiveGroupId;
222 }
223 }
224 catch
225 {
226 return true;
227 }
228 }
229 }
230
231 public bool ParcelHideThisAvatar
232 {
233 get
234 {
235 return m_currentParcelHide;
236 }
237 }
238
147 /// <value> 239 /// <value>
148 /// The animator for this avatar 240 /// The animator for this avatar
149 /// </value> 241 /// </value>
150 public ScenePresenceAnimator Animator { get; private set; } 242 public ScenePresenceAnimator Animator { get; private set; }
151 243
244 /// <value>
245 /// Server Side Animation Override
246 /// </value>
247 public MovementAnimationOverrides Overrides { get; private set; }
248 public String sitAnimation = "SIT";
152 /// <summary> 249 /// <summary>
153 /// Attachments recorded on this avatar. 250 /// Attachments recorded on this avatar.
154 /// </summary> 251 /// </summary>
@@ -192,14 +289,7 @@ namespace OpenSim.Region.Framework.Scenes
192 set { PhysicsActor.Flying = value; } 289 set { PhysicsActor.Flying = value; }
193 } 290 }
194 291
195 // add for fly velocity control 292 public bool IsColliding
196 private bool FlyingOld {get; set;}
197 public bool WasFlying
198 {
199 get; private set;
200 }
201
202 public bool IsColliding
203 { 293 {
204 get { return PhysicsActor != null && PhysicsActor.IsColliding; } 294 get { return PhysicsActor != null && PhysicsActor.IsColliding; }
205 // We would expect setting IsColliding to be private but it's used by a hack in Scene 295 // We would expect setting IsColliding to be private but it's used by a hack in Scene
@@ -209,6 +299,7 @@ namespace OpenSim.Region.Framework.Scenes
209// private int m_lastColCount = -1; //KF: Look for Collision chnages 299// private int m_lastColCount = -1; //KF: Look for Collision chnages
210// private int m_updateCount = 0; //KF: Update Anims for a while 300// private int m_updateCount = 0; //KF: Update Anims for a while
211// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 301// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
302 private List<uint> m_lastColliders = new List<uint>();
212 303
213 private TeleportFlags m_teleportFlags; 304 private TeleportFlags m_teleportFlags;
214 public TeleportFlags TeleportFlags 305 public TeleportFlags TeleportFlags
@@ -247,7 +338,7 @@ namespace OpenSim.Region.Framework.Scenes
247 338
248 protected ulong crossingFromRegion; 339 protected ulong crossingFromRegion;
249 340
250 private readonly Vector3[] Dir_Vectors = new Vector3[11]; 341 private readonly Vector3[] Dir_Vectors = new Vector3[12];
251 342
252 protected Timer m_reprioritization_timer; 343 protected Timer m_reprioritization_timer;
253 protected bool m_reprioritizing; 344 protected bool m_reprioritizing;
@@ -271,6 +362,9 @@ namespace OpenSim.Region.Framework.Scenes
271 //private int m_moveToPositionStateStatus; 362 //private int m_moveToPositionStateStatus;
272 //***************************************************** 363 //*****************************************************
273 364
365 private bool m_collisionEventFlag = false;
366 private object m_collisionEventLock = new Object();
367
274 private int m_movementAnimationUpdateCounter = 0; 368 private int m_movementAnimationUpdateCounter = 0;
275 369
276 public Vector3 PrevSitOffset { get; set; } 370 public Vector3 PrevSitOffset { get; set; }
@@ -287,7 +381,6 @@ namespace OpenSim.Region.Framework.Scenes
287 } 381 }
288 } 382 }
289 383
290 public bool SentInitialDataToClient { get; private set; }
291 384
292 /// <summary> 385 /// <summary>
293 /// Copy of the script states while the agent is in transit. This state may 386 /// Copy of the script states while the agent is in transit. This state may
@@ -303,7 +396,7 @@ namespace OpenSim.Region.Framework.Scenes
303 /// <summary> 396 /// <summary>
304 /// Implemented Control Flags 397 /// Implemented Control Flags
305 /// </summary> 398 /// </summary>
306 private enum Dir_ControlFlags 399 private enum Dir_ControlFlags:uint
307 { 400 {
308 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, 401 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
309 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, 402 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
@@ -315,6 +408,7 @@ namespace OpenSim.Region.Framework.Scenes
315 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 408 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
316 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, 409 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
317 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, 410 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
411 DIR_CONTROL_FLAG_UP_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS,
318 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 412 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
319 } 413 }
320 414
@@ -347,12 +441,6 @@ namespace OpenSim.Region.Framework.Scenes
347 private object m_originRegionIDAccessLock = new object(); 441 private object m_originRegionIDAccessLock = new object();
348 442
349 /// <summary> 443 /// <summary>
350 /// Triggered on entity transfer after to allow CompleteMovement() to proceed after we have received an
351 /// UpdateAgent from the originating region.ddkjjkj
352 /// </summary>
353 private AutoResetEvent m_updateAgentReceivedAfterTransferEvent = new AutoResetEvent(false);
354
355 /// <summary>
356 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent 444 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
357 /// teleport is reusing the connection. 445 /// teleport is reusing the connection.
358 /// </summary> 446 /// </summary>
@@ -379,11 +467,6 @@ namespace OpenSim.Region.Framework.Scenes
379 public uint MovementFlag { get; private set; } 467 public uint MovementFlag { get; private set; }
380 468
381 /// <summary> 469 /// <summary>
382 /// Set this if we need to force a movement update on the next received AgentUpdate from the viewer.
383 /// </summary>
384 private const uint ForceUpdateMovementFlagValue = uint.MaxValue;
385
386 /// <summary>
387 /// Is the agent stop control flag currently active? 470 /// Is the agent stop control flag currently active?
388 /// </summary> 471 /// </summary>
389 public bool AgentControlStopActive { get; private set; } 472 public bool AgentControlStopActive { get; private set; }
@@ -413,11 +496,18 @@ namespace OpenSim.Region.Framework.Scenes
413 } 496 }
414 497
415 private ulong m_rootRegionHandle; 498 private ulong m_rootRegionHandle;
499 private Vector3 m_rootRegionPosition = new Vector3();
416 500
417 public ulong RegionHandle 501 public ulong RegionHandle
418 { 502 {
419 get { return m_rootRegionHandle; } 503 get { return m_rootRegionHandle; }
420 private set { m_rootRegionHandle = value; } 504 private set
505 {
506 m_rootRegionHandle = value;
507 // position rounded to lower multiple of 256m
508 m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00);
509 m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00);
510 }
421 } 511 }
422 512
423 #region Client Camera 513 #region Client Camera
@@ -449,11 +539,8 @@ namespace OpenSim.Region.Framework.Scenes
449 get 539 get
450 { 540 {
451 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); 541 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0);
452 542 a.Normalize();
453 if (a == Vector3.Zero) 543 return a;
454 return a;
455
456 return Util.GetNormalizedVector(a);
457 } 544 }
458 } 545 }
459 #endregion 546 #endregion
@@ -474,9 +561,19 @@ namespace OpenSim.Region.Framework.Scenes
474 /// </summary> 561 /// </summary>
475 public bool UseFakeGroupTitle { get; set; } 562 public bool UseFakeGroupTitle { get; set; }
476 563
477
478 // Agent's Draw distance. 564 // Agent's Draw distance.
479 public float DrawDistance { get; set; } 565 private float m_drawDistance = 255f;
566 public float DrawDistance
567 {
568 get
569 {
570 return m_drawDistance;
571 }
572 set
573 {
574 m_drawDistance = Util.Clamp(value, 32f, m_scene.MaxDrawDistance);
575 }
576 }
480 577
481 public bool AllowMovement { get; set; } 578 public bool AllowMovement { get; set; }
482 579
@@ -505,6 +602,7 @@ namespace OpenSim.Region.Framework.Scenes
505 } 602 }
506 } 603 }
507 604
605
508 public byte State { get; set; } 606 public byte State { get; set; }
509 607
510 private AgentManager.ControlFlags m_AgentControlFlags; 608 private AgentManager.ControlFlags m_AgentControlFlags;
@@ -557,10 +655,14 @@ namespace OpenSim.Region.Framework.Scenes
557 // in the sim unless the avatar is on a sit target. While 655 // in the sim unless the avatar is on a sit target. While
558 // on a sit target, m_pos will contain the desired offset 656 // on a sit target, m_pos will contain the desired offset
559 // without the parent rotation applied. 657 // without the parent rotation applied.
560 SceneObjectPart sitPart = ParentPart; 658 if (ParentPart != null)
561 659 {
562 if (sitPart != null) 660 SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
563 return sitPart.ParentGroup.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 661 // if (sitPart != null)
662 // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
663 if (rootPart != null)
664 return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
665 }
564 } 666 }
565 667
566 return m_pos; 668 return m_pos;
@@ -614,11 +716,8 @@ namespace OpenSim.Region.Framework.Scenes
614 } 716 }
615 717
616 /// <summary> 718 /// <summary>
617 /// Velocity of the avatar with respect to its local reference frame. 719 /// Current velocity of the avatar.
618 /// </summary> 720 /// </summary>
619 /// <remarks>
620 /// So when sat on a vehicle this will be 0. To get velocity with respect to the world use GetWorldVelocity()
621 /// </remarks>
622 public override Vector3 Velocity 721 public override Vector3 Velocity
623 { 722 {
624 get 723 get
@@ -631,21 +730,12 @@ namespace OpenSim.Region.Framework.Scenes
631// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", 730// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
632// m_velocity, Name, Scene.RegionInfo.RegionName); 731// m_velocity, Name, Scene.RegionInfo.RegionName);
633 } 732 }
634// else if (ParentPart != null)
635// {
636// return ParentPart.ParentGroup.Velocity;
637// }
638 733
639 return m_velocity; 734 return m_velocity;
640 } 735 }
641 736
642 set 737 set
643 { 738 {
644// Util.PrintCallStack();
645// m_log.DebugFormat(
646// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
647// Scene.RegionInfo.RegionName, Name, value);
648
649 if (PhysicsActor != null) 739 if (PhysicsActor != null)
650 { 740 {
651 try 741 try
@@ -658,27 +748,14 @@ namespace OpenSim.Region.Framework.Scenes
658 } 748 }
659 } 749 }
660 750
661 m_velocity = value; 751 m_velocity = value;
662 }
663 }
664/*
665 public override Vector3 AngularVelocity
666 {
667 get
668 {
669 if (PhysicsActor != null)
670 {
671 m_rotationalvelocity = PhysicsActor.RotationalVelocity;
672
673 // m_log.DebugFormat(
674 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
675 // m_velocity, Name, Scene.RegionInfo.RegionName);
676 }
677 752
678 return m_rotationalvelocity; 753// m_log.DebugFormat(
754// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
755// Scene.RegionInfo.RegionName, Name, m_velocity);
679 } 756 }
680 } 757 }
681*/ 758
682 private Quaternion m_bodyRot = Quaternion.Identity; 759 private Quaternion m_bodyRot = Quaternion.Identity;
683 760
684 /// <summary> 761 /// <summary>
@@ -759,15 +836,21 @@ namespace OpenSim.Region.Framework.Scenes
759 } 836 }
760 837
761 /// <summary> 838 /// <summary>
762 /// Get rotation relative to the world. 839 /// Gets the world rotation of this presence.
763 /// </summary> 840 /// </summary>
841 /// <remarks>
842 /// Unlike Rotation, this returns the world rotation no matter whether the avatar is sitting on a prim or not.
843 /// </remarks>
764 /// <returns></returns> 844 /// <returns></returns>
765 public Quaternion GetWorldRotation() 845 public Quaternion GetWorldRotation()
766 { 846 {
767 SceneObjectPart sitPart = ParentPart; 847 if (IsSatOnObject)
848 {
849 SceneObjectPart sitPart = ParentPart;
768 850
769 if (sitPart != null) 851 if (sitPart != null)
770 return sitPart.GetWorldRotation() * Rotation; 852 return sitPart.GetWorldRotation() * Rotation;
853 }
771 854
772 return Rotation; 855 return Rotation;
773 } 856 }
@@ -794,22 +877,23 @@ namespace OpenSim.Region.Framework.Scenes
794 else 877 else
795 seeds = new Dictionary<ulong, string>(); 878 seeds = new Dictionary<ulong, string>();
796 879
880/* we can't do this anymore
797 List<ulong> old = new List<ulong>(); 881 List<ulong> old = new List<ulong>();
798 foreach (ulong handle in seeds.Keys) 882 foreach (ulong handle in seeds.Keys)
799 { 883 {
800 uint x, y; 884 uint x, y;
801 Util.RegionHandleToRegionLoc(handle, out x, out y); 885 Util.RegionHandleToRegionLoc(handle, out x, out y);
802 886// if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY,))
803 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
804 { 887 {
805 old.Add(handle); 888 old.Add(handle);
806 } 889 }
807 } 890 }
891
808 DropOldNeighbours(old); 892 DropOldNeighbours(old);
809 893
810 if (Scene.CapsModule != null) 894 if (Scene.CapsModule != null)
811 Scene.CapsModule.SetChildrenSeed(UUID, seeds); 895 Scene.CapsModule.SetChildrenSeed(UUID, seeds);
812 896*/
813 KnownRegions = seeds; 897 KnownRegions = seeds;
814 //m_log.Debug(" ++++++++++AFTER+++++++++++++ "); 898 //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
815 //DumpKnownRegions(); 899 //DumpKnownRegions();
@@ -827,7 +911,7 @@ namespace OpenSim.Region.Framework.Scenes
827 } 911 }
828 912
829 private bool m_mouseLook; 913 private bool m_mouseLook;
830// private bool m_leftButtonDown; 914 private bool m_leftButtonDown;
831 915
832 private bool m_inTransit; 916 private bool m_inTransit;
833 917
@@ -852,13 +936,6 @@ namespace OpenSim.Region.Framework.Scenes
852 } 936 }
853 } 937 }
854 938
855 private float m_speedModifier = 1.0f;
856
857 public float SpeedModifier
858 {
859 get { return m_speedModifier; }
860 set { m_speedModifier = value; }
861 }
862 939
863 /// <summary> 940 /// <summary>
864 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running 941 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
@@ -866,7 +943,20 @@ namespace OpenSim.Region.Framework.Scenes
866 /// <remarks> 943 /// <remarks>
867 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. 944 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
868 /// </remarks> 945 /// </remarks>
869 private float AgentControlStopSlowWhilstMoving = 0.5f; 946 private const float AgentControlStopSlowVel = 0.2f;
947 // velocities
948 public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently
949 public const float AgentControlNormalVel = 1.0f;
950
951 // old normal speed was tuned to match sl normal plus Fast modifiers
952 // so we need to rescale it
953 private float m_speedModifier = 1.0f;
954
955 public float SpeedModifier
956 {
957 get { return m_speedModifier; }
958 set { m_speedModifier = value; }
959 }
870 960
871 private bool m_forceFly; 961 private bool m_forceFly;
872 962
@@ -888,12 +978,7 @@ namespace OpenSim.Region.Framework.Scenes
888 { 978 {
889 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); } 979 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); }
890 } 980 }
891 981
892 /// <summary>
893 /// Count of how many terse updates we have sent out. It doesn't matter if this overflows.
894 /// </summary>
895 private int m_terseUpdateCount;
896
897 #endregion 982 #endregion
898 983
899 #region Constructor(s) 984 #region Constructor(s)
@@ -901,21 +986,21 @@ namespace OpenSim.Region.Framework.Scenes
901 public ScenePresence( 986 public ScenePresence(
902 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 987 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
903 { 988 {
989 m_scene = world;
904 AttachmentsSyncLock = new Object(); 990 AttachmentsSyncLock = new Object();
905 AllowMovement = true; 991 AllowMovement = true;
906 IsChildAgent = true; 992 IsChildAgent = true;
907 IsLoggingIn = false; 993 IsLoggingIn = false;
908 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 994 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
909 Animator = new ScenePresenceAnimator(this); 995 Animator = new ScenePresenceAnimator(this);
996 Overrides = new MovementAnimationOverrides();
910 PresenceType = type; 997 PresenceType = type;
911 // DrawDistance = world.DefaultDrawDistance; 998 DrawDistance = world.DefaultDrawDistance;
912 DrawDistance = Constants.RegionSize;
913 RegionHandle = world.RegionInfo.RegionHandle; 999 RegionHandle = world.RegionInfo.RegionHandle;
914 ControllingClient = client; 1000 ControllingClient = client;
915 Firstname = ControllingClient.FirstName; 1001 Firstname = ControllingClient.FirstName;
916 Lastname = ControllingClient.LastName; 1002 Lastname = ControllingClient.LastName;
917 m_name = String.Format("{0} {1}", Firstname, Lastname); 1003 m_name = String.Format("{0} {1}", Firstname, Lastname);
918 m_scene = world;
919 m_uuid = client.AgentId; 1004 m_uuid = client.AgentId;
920 LocalId = m_scene.AllocateLocalId(); 1005 LocalId = m_scene.AllocateLocalId();
921 1006
@@ -930,7 +1015,7 @@ namespace OpenSim.Region.Framework.Scenes
930 1015
931 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1016 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
932 if (gm != null) 1017 if (gm != null)
933 Grouptitle = gm.GetGroupTitle(m_uuid); 1018 Grouptitle = gm.GetGroupTitle(m_uuid);
934 1019
935 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 1020 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
936 1021
@@ -988,8 +1073,10 @@ namespace OpenSim.Region.Framework.Scenes
988 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 1073 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
989 ControllingClient.OnStartAnim += HandleStartAnim; 1074 ControllingClient.OnStartAnim += HandleStartAnim;
990 ControllingClient.OnStopAnim += HandleStopAnim; 1075 ControllingClient.OnStopAnim += HandleStopAnim;
1076 ControllingClient.OnChangeAnim += avnHandleChangeAnim;
991 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; 1077 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
992 ControllingClient.OnAutoPilotGo += MoveToTarget; 1078 ControllingClient.OnAutoPilotGo += MoveToTarget;
1079 ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles;
993 1080
994 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); 1081 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
995 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); 1082 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
@@ -997,19 +1084,19 @@ namespace OpenSim.Region.Framework.Scenes
997 1084
998 private void SetDirectionVectors() 1085 private void SetDirectionVectors()
999 { 1086 {
1000 Dir_Vectors[0] = Vector3.UnitX; //FORWARD 1087 Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD
1001 Dir_Vectors[1] = -Vector3.UnitX; //BACK 1088 Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK
1002 Dir_Vectors[2] = Vector3.UnitY; //LEFT 1089 Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT
1003 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 1090 Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT
1004 Dir_Vectors[4] = Vector3.UnitZ; //UP 1091 Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP
1005 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 1092 Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN
1006 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE 1093 Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE
1007 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE 1094 Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE
1008 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE 1095 Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE
1009 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE 1096 Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE
1010 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 1097 Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge
1098 Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge
1011 } 1099 }
1012
1013 #endregion 1100 #endregion
1014 1101
1015 #region Status Methods 1102 #region Status Methods
@@ -1026,18 +1113,25 @@ namespace OpenSim.Region.Framework.Scenes
1026 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1113 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
1027 /// delays that crossing. 1114 /// delays that crossing.
1028 /// </remarks> 1115 /// </remarks>
1116
1117
1118 // only in use as part of completemovement
1119 // other uses need fix
1029 private bool MakeRootAgent(Vector3 pos, bool isFlying) 1120 private bool MakeRootAgent(Vector3 pos, bool isFlying)
1030 { 1121 {
1122 int ts = Util.EnvironmentTickCount();
1123
1031 lock (m_completeMovementLock) 1124 lock (m_completeMovementLock)
1032 { 1125 {
1033 if (!IsChildAgent) 1126 if (!IsChildAgent)
1034 return false; 1127 return false;
1035 1128
1129 m_log.DebugFormat("[MakeRootAgent] enter lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1036 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 1130 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1037 1131
1038 // m_log.InfoFormat( 1132 // m_log.InfoFormat(
1039 // "[SCENE]: Upgrading child to root agent for {0} in {1}", 1133 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1040 // Name, m_scene.RegionInfo.RegionName); 1134 // Name, m_scene.RegionInfo.RegionName);
1041 1135
1042 if (ParentUUID != UUID.Zero) 1136 if (ParentUUID != UUID.Zero)
1043 { 1137 {
@@ -1046,20 +1140,23 @@ namespace OpenSim.Region.Framework.Scenes
1046 if (part == null) 1140 if (part == null)
1047 { 1141 {
1048 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1142 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1143 ParentID = 0;
1144 ParentPart = null;
1145 PrevSitOffset = Vector3.Zero;
1146 HandleForceReleaseControls(ControllingClient, UUID); // needs testing
1147 IsLoggingIn = false;
1049 } 1148 }
1050 else 1149 else
1051 { 1150 {
1052 part.AddSittingAvatar(this); 1151 part.AddSittingAvatar(this);
1053 // ParentPosition = part.GetWorldPosition(); 1152 if (part.SitTargetPosition != Vector3.Zero)
1153 part.SitTargetAvatar = UUID;
1054 ParentID = part.LocalId; 1154 ParentID = part.LocalId;
1055 ParentPart = part; 1155 ParentPart = part;
1056 m_pos = PrevSitOffset; 1156 m_pos = PrevSitOffset;
1057 // pos = ParentPosition;
1058 pos = part.GetWorldPosition(); 1157 pos = part.GetWorldPosition();
1059 } 1158 }
1060 ParentUUID = UUID.Zero; 1159 ParentUUID = UUID.Zero;
1061
1062 // Animator.TrySetMovementAnimation("SIT");
1063 } 1160 }
1064 else 1161 else
1065 { 1162 {
@@ -1069,82 +1166,36 @@ namespace OpenSim.Region.Framework.Scenes
1069 IsChildAgent = false; 1166 IsChildAgent = false;
1070 } 1167 }
1071 1168
1169 m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1170
1072 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag 1171 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1073 // set and prevent the close of the connection on a subsequent re-teleport. 1172 // set and prevent the close of the connection on a subsequent re-teleport.
1074 // Should not be needed if we are not trying to tell this region to close 1173 // Should not be needed if we are not trying to tell this region to close
1075// DoNotCloseAfterTeleport = false; 1174 // DoNotCloseAfterTeleport = false;
1076 1175
1077 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1176 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
1078 if (gm != null) 1177 if (gm != null)
1079 Grouptitle = gm.GetGroupTitle(m_uuid); 1178 Grouptitle = gm.GetGroupTitle(m_uuid);
1080 1179
1081 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode); 1180
1082 uint teleportFlags = (aCircuit == null) ? 0 : aCircuit.teleportFlags; 1181 if ((m_teleportFlags & TeleportFlags.ViaHGLogin) != 0)
1083 if ((teleportFlags & (uint)TeleportFlags.ViaHGLogin) != 0)
1084 { 1182 {
1085 // The avatar is arriving from another grid. This means that we may have changed the 1183 // The avatar is arriving from another grid. This means that we may have changed the
1086 // avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com"). 1184 // avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com").
1087 // Unfortunately, due to a viewer bug, viewers don't always show the new name. 1185 // Unfortunately, due to a viewer bug, viewers don't always show the new name.
1088 // But we have a trick that can force them to update the name anyway. 1186 // But we have a trick that can force them to update the name anyway.
1089 ForceViewersUpdateName(); 1187// ForceViewersUpdateName();
1090 } 1188 }
1091 1189
1190 m_log.DebugFormat("[MakeRootAgent] Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1191
1092 RegionHandle = m_scene.RegionInfo.RegionHandle; 1192 RegionHandle = m_scene.RegionInfo.RegionHandle;
1093 1193
1094 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1194 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
1095 1195 m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1096 UUID groupUUID = ControllingClient.ActiveGroupId;
1097 string groupName = string.Empty;
1098 ulong groupPowers = 0;
1099
1100 // ----------------------------------
1101 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
1102 try
1103 {
1104 if (groupUUID != UUID.Zero && gm != null)
1105 {
1106 GroupRecord record = gm.GetGroupRecord(groupUUID);
1107 if (record != null)
1108 groupName = record.GroupName;
1109
1110 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
1111
1112 if (groupMembershipData != null)
1113 groupPowers = groupMembershipData.GroupPowers;
1114 }
1115
1116 ControllingClient.SendAgentDataUpdate(
1117 m_uuid, groupUUID, Firstname, Lastname, groupPowers, groupName, Grouptitle);
1118 }
1119 catch (Exception e)
1120 {
1121 m_log.Error("[AGENTUPDATE]: Error ", e);
1122 }
1123 // ------------------------------------
1124 1196
1125 if (ParentID == 0) 1197 if (ParentID == 0)
1126 { 1198 {
1127 // Moved this from SendInitialData to ensure that Appearance is initialized
1128 // before the inventory is processed in MakeRootAgent. This fixes a race condition
1129 // related to the handling of attachments
1130 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
1131
1132 /* RA 20140111: Commented out these TestBorderCross's.
1133 * Not sure why this code is here. It is not checking all the borders
1134 * and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below.
1135 if (m_scene.TestBorderCross(pos, Cardinals.E))
1136 {
1137 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
1138 pos.X = crossedBorder.BorderLine.Z - 1;
1139 }
1140
1141 if (m_scene.TestBorderCross(pos, Cardinals.N))
1142 {
1143 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
1144 pos.Y = crossedBorder.BorderLine.Z - 1;
1145 }
1146 */
1147
1148 CheckAndAdjustLandingPoint(ref pos); 1199 CheckAndAdjustLandingPoint(ref pos);
1149 1200
1150 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1201 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -1166,7 +1217,7 @@ namespace OpenSim.Region.Framework.Scenes
1166 1217
1167 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY) 1218 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
1168 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1219 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1169 1220
1170 float newPosZ = posZLimit + localAVHeight / 2; 1221 float newPosZ = posZLimit + localAVHeight / 2;
1171 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 1222 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
1172 { 1223 {
@@ -1180,24 +1231,18 @@ namespace OpenSim.Region.Framework.Scenes
1180// 1231//
1181 if (m_teleportFlags == TeleportFlags.Default) 1232 if (m_teleportFlags == TeleportFlags.Default)
1182 { 1233 {
1234 Vector3 vel = Velocity;
1183 AddToPhysicalScene(isFlying); 1235 AddToPhysicalScene(isFlying);
1184// 1236 if (PhysicsActor != null)
1185// Console.WriteLine( 1237 PhysicsActor.SetMomentum(vel);
1186// "Set velocity of {0} in {1} to {2} from input velocity of {3} on MakeRootAgent",
1187// Name, Scene.Name, PhysicsActor.Velocity, vel);
1188// }
1189 } 1238 }
1190 else 1239 else
1191 { 1240 {
1192 AddToPhysicalScene(isFlying); 1241 AddToPhysicalScene(isFlying);
1193 }
1194 1242
1195 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a 1243 // reset camera to avatar pos
1196 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it 1244 CameraPosition = pos;
1197 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset 1245 }
1198 // the value to a negative position which does not trigger the border cross.
1199 // This may not be the best location for this.
1200 CheckForBorderCrossing();
1201 1246
1202 if (ForceFly) 1247 if (ForceFly)
1203 { 1248 {
@@ -1207,55 +1252,29 @@ namespace OpenSim.Region.Framework.Scenes
1207 { 1252 {
1208 Flying = false; 1253 Flying = false;
1209 } 1254 }
1210 }
1211 1255
1212 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 1256 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1213 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 1257 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1214 // elsewhere anyway 1258 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1215 // Animator.SendAnimPack(); 1259 // the value to a negative position which does not trigger the border cross.
1260 // This may not be the best location for this.
1216 1261
1217 m_scene.SwapRootAgentCount(false);
1218 1262
1219 if (Scene.AttachmentsModule != null) 1263 // its not
1220 { 1264// CheckForBorderCrossing();
1221 // The initial login scene presence is already root when it gets here
1222 // and it has already rezzed the attachments and started their scripts.
1223 // We do the following only for non-login agents, because their scripts
1224 // haven't started yet.
1225 if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))
1226 {
1227 WorkManager.RunJob(
1228 "RezAttachments",
1229 o => Scene.AttachmentsModule.RezAttachments(this),
1230 null,
1231 string.Format("Rez attachments for {0} in {1}", Name, Scene.Name));
1232 }
1233 else
1234 {
1235 WorkManager.RunJob(
1236 "StartAttachmentScripts",
1237 o => RestartAttachmentScripts(),
1238 null,
1239 string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name),
1240 true);
1241 }
1242 } 1265 }
1243 1266
1244 SendAvatarDataToAllClients(); 1267
1245 1268 m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1246 // send the animations of the other presences to me 1269 m_scene.SwapRootAgentCount(false);
1247 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1248 {
1249 if (presence != this)
1250 presence.Animator.SendAnimPackToClient(ControllingClient);
1251 });
1252 1270
1253 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1271 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
1254 // stall on the border crossing since the existing child agent will still have the last movement 1272 // stall on the border crossing since the existing child agent will still have the last movement
1255 // recorded, which stops the input from being processed. 1273 // recorded, which stops the input from being processed.
1256 MovementFlag = ForceUpdateMovementFlagValue; 1274 MovementFlag = 0;
1257 1275
1258 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1276 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1277 m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1259 1278
1260 return true; 1279 return true;
1261 } 1280 }
@@ -1304,12 +1323,13 @@ namespace OpenSim.Region.Framework.Scenes
1304 /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing 1323 /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing
1305 /// the group title (to "(Loading)"), and then restoring it. 1324 /// the group title (to "(Loading)"), and then restoring it.
1306 /// </remarks> 1325 /// </remarks>
1326/*
1307 public void ForceViewersUpdateName() 1327 public void ForceViewersUpdateName()
1308 { 1328 {
1309 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name); 1329 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name);
1310 1330
1311 UseFakeGroupTitle = true; 1331 UseFakeGroupTitle = true;
1312 SendAvatarDataToAllClients(false); 1332
1313 1333
1314 Util.FireAndForget(o => 1334 Util.FireAndForget(o =>
1315 { 1335 {
@@ -1323,7 +1343,7 @@ namespace OpenSim.Region.Framework.Scenes
1323 SendAvatarDataToAllClients(false); 1343 SendAvatarDataToAllClients(false);
1324 }, null, "Scenepresence.ForceViewersUpdateName"); 1344 }, null, "Scenepresence.ForceViewersUpdateName");
1325 } 1345 }
1326 1346*/
1327 public int GetStateSource() 1347 public int GetStateSource()
1328 { 1348 {
1329 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID); 1349 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID);
@@ -1347,11 +1367,14 @@ namespace OpenSim.Region.Framework.Scenes
1347 /// It doesn't get called for a teleport. Reason being, an agent that 1367 /// It doesn't get called for a teleport. Reason being, an agent that
1348 /// teleports out may not end up anywhere near this region 1368 /// teleports out may not end up anywhere near this region
1349 /// </remarks> 1369 /// </remarks>
1350 public void MakeChildAgent() 1370 public void MakeChildAgent(ulong newRegionHandle)
1351 { 1371 {
1352 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; 1372 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1353 1373
1354 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1374 RegionHandle = newRegionHandle;
1375
1376 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}",
1377 Name, Scene.RegionInfo.RegionName, newRegionHandle);
1355 1378
1356 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating 1379 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1357 // from the source simulator has completed on a V2 teleport. 1380 // from the source simulator has completed on a V2 teleport.
@@ -1371,7 +1394,7 @@ namespace OpenSim.Region.Framework.Scenes
1371 else 1394 else
1372 Animator.ResetAnimations(); 1395 Animator.ResetAnimations();
1373 1396
1374 1397
1375// m_log.DebugFormat( 1398// m_log.DebugFormat(
1376// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1399// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1377// Name, UUID, m_scene.RegionInfo.RegionName); 1400// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1385,8 +1408,15 @@ namespace OpenSim.Region.Framework.Scenes
1385 RemoveFromPhysicalScene(); 1408 RemoveFromPhysicalScene();
1386 ParentID = 0; // Child agents can't be sitting 1409 ParentID = 0; // Child agents can't be sitting
1387 1410
1411// we dont have land information for child
1412 m_previusParcelHide = false;
1413 m_previusParcelUUID = UUID.Zero;
1414 m_currentParcelHide = false;
1415 m_currentParcelUUID = UUID.Zero;
1388 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1416 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
1389 1417
1418 CollisionPlane = Vector4.UnitW;
1419
1390 m_scene.EventManager.TriggerOnMakeChildAgent(this); 1420 m_scene.EventManager.TriggerOnMakeChildAgent(this);
1391 } 1421 }
1392 1422
@@ -1398,9 +1428,10 @@ namespace OpenSim.Region.Framework.Scenes
1398 if (PhysicsActor != null) 1428 if (PhysicsActor != null)
1399 { 1429 {
1400// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1430// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1401 PhysicsActor.UnSubscribeEvents(); 1431
1402 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; 1432 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
1403 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1433 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1434 PhysicsActor.UnSubscribeEvents();
1404 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1435 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1405 PhysicsActor = null; 1436 PhysicsActor = null;
1406 } 1437 }
@@ -1438,6 +1469,8 @@ namespace OpenSim.Region.Framework.Scenes
1438 else 1469 else
1439 PhysicsActor.SetMomentum(vel); 1470 PhysicsActor.SetMomentum(vel);
1440 } 1471 }
1472
1473 SendTerseUpdateToAllClients();
1441 } 1474 }
1442 1475
1443 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY) 1476 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
@@ -1469,10 +1502,14 @@ namespace OpenSim.Region.Framework.Scenes
1469 } 1502 }
1470 } 1503 }
1471 } 1504 }
1505 SendTerseUpdateToAllClients();
1472 } 1506 }
1473 1507
1474 public void StopFlying() 1508 public void StopFlying()
1475 { 1509 {
1510 if (IsInTransit)
1511 return;
1512
1476 Vector3 pos = AbsolutePosition; 1513 Vector3 pos = AbsolutePosition;
1477 if (Appearance.AvatarHeight != 127.0f) 1514 if (Appearance.AvatarHeight != 127.0f)
1478 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); 1515 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
@@ -1492,7 +1529,7 @@ namespace OpenSim.Region.Framework.Scenes
1492 else 1529 else
1493 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); 1530 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1494 1531
1495 ControllingClient.SendAgentTerseUpdate(this); 1532 SendAgentTerseUpdate(this);
1496 } 1533 }
1497 1534
1498 /// <summary> 1535 /// <summary>
@@ -1578,15 +1615,46 @@ namespace OpenSim.Region.Framework.Scenes
1578 // holds the seed cap for the child agent in that region 1615 // holds the seed cap for the child agent in that region
1579 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>(); 1616 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
1580 1617
1581 public void AddNeighbourRegion(ulong regionHandle, string cap) 1618 struct spRegionSizeInfo
1619 {
1620 public int sizeX;
1621 public int sizeY;
1622 }
1623
1624 private Dictionary<ulong, spRegionSizeInfo> m_knownChildRegionsSizeInfo = new Dictionary<ulong, spRegionSizeInfo>();
1625
1626
1627 public void AddNeighbourRegionSizeInfo(GridRegion region)
1628 {
1629 lock (m_knownChildRegions)
1630 {
1631 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1632 sizeInfo.sizeX = region.RegionSizeX;
1633 sizeInfo.sizeY = region.RegionSizeY;
1634 ulong regionHandle = region.RegionHandle;
1635
1636 if (!m_knownChildRegionsSizeInfo.ContainsKey(regionHandle))
1637 {
1638 m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1639
1640 }
1641 else
1642 m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo;
1643 }
1644 }
1645
1646 public void SetNeighbourRegionSizeInfo(List<GridRegion> regionsList)
1582 { 1647 {
1583 lock (m_knownChildRegions) 1648 lock (m_knownChildRegions)
1584 { 1649 {
1585 if (!m_knownChildRegions.ContainsKey(regionHandle)) 1650 m_knownChildRegionsSizeInfo.Clear();
1651 foreach (GridRegion region in regionsList)
1586 { 1652 {
1587 uint x, y; 1653 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1588 Utils.LongToUInts(regionHandle, out x, out y); 1654 sizeInfo.sizeX = region.RegionSizeX;
1589 m_knownChildRegions.Add(regionHandle, cap); 1655 sizeInfo.sizeY = region.RegionSizeY;
1656 ulong regionHandle = region.RegionHandle;
1657 m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1590 } 1658 }
1591 } 1659 }
1592 } 1660 }
@@ -1600,6 +1668,7 @@ namespace OpenSim.Region.Framework.Scenes
1600 //if (m_knownChildRegions.ContainsKey(regionHandle)) 1668 //if (m_knownChildRegions.ContainsKey(regionHandle))
1601 // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); 1669 // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
1602 m_knownChildRegions.Remove(regionHandle); 1670 m_knownChildRegions.Remove(regionHandle);
1671 m_knownChildRegionsSizeInfo.Remove(regionHandle);
1603 } 1672 }
1604 } 1673 }
1605 1674
@@ -1612,6 +1681,13 @@ namespace OpenSim.Region.Framework.Scenes
1612 } 1681 }
1613 } 1682 }
1614 1683
1684 public void DropThisRootRegionFromNeighbours()
1685 {
1686 ulong handle = m_scene.RegionInfo.RegionHandle;
1687 RemoveNeighbourRegion(handle);
1688 Scene.CapsModule.DropChildSeed(UUID, handle);
1689 }
1690
1615 public Dictionary<ulong, string> KnownRegions 1691 public Dictionary<ulong, string> KnownRegions
1616 { 1692 {
1617 get 1693 get
@@ -1662,12 +1738,7 @@ namespace OpenSim.Region.Framework.Scenes
1662 public void SetSize(Vector3 size, float feetoffset) 1738 public void SetSize(Vector3 size, float feetoffset)
1663 { 1739 {
1664 if (PhysicsActor != null && !IsChildAgent) 1740 if (PhysicsActor != null && !IsChildAgent)
1665 { 1741 PhysicsActor.setAvatarSize(size, feetoffset);
1666 // Eventually there will be a physics call that sets avatar size that includes offset info.
1667 // For the moment, just set the size as passed.
1668 PhysicsActor.Size = size;
1669 // PhysicsActor.setAvatarSize(size, feetoffset);
1670 }
1671 } 1742 }
1672 1743
1673 private bool WaitForUpdateAgent(IClientAPI client) 1744 private bool WaitForUpdateAgent(IClientAPI client)
@@ -1676,13 +1747,23 @@ namespace OpenSim.Region.Framework.Scenes
1676 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, 1747 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1677 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the 1748 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1678 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero 1749 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1679 m_updateAgentReceivedAfterTransferEvent.WaitOne(10000); 1750// m_updateAgentReceivedAfterTransferEvent.WaitOne(10000);
1680 1751 int count = 50;
1681 UUID originID = UUID.Zero; 1752 UUID originID = UUID.Zero;
1682 1753
1683 lock (m_originRegionIDAccessLock) 1754 lock (m_originRegionIDAccessLock)
1684 originID = m_originRegionID; 1755 originID = m_originRegionID;
1685 1756
1757
1758 while (originID.Equals(UUID.Zero) && count-- > 0)
1759 {
1760 lock (m_originRegionIDAccessLock)
1761 originID = m_originRegionID;
1762
1763 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1764 Thread.Sleep(200);
1765 }
1766
1686 if (originID.Equals(UUID.Zero)) 1767 if (originID.Equals(UUID.Zero))
1687 { 1768 {
1688 // Movement into region will fail 1769 // Movement into region will fail
@@ -1704,62 +1785,70 @@ namespace OpenSim.Region.Framework.Scenes
1704 /// </param> 1785 /// </param>
1705 public void CompleteMovement(IClientAPI client, bool openChildAgents) 1786 public void CompleteMovement(IClientAPI client, bool openChildAgents)
1706 { 1787 {
1707// DateTime startTime = DateTime.Now; 1788 int ts = Util.EnvironmentTickCount();
1708 1789
1709 m_log.InfoFormat( 1790 m_log.InfoFormat(
1710 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1791 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1711 client.Name, Scene.Name, AbsolutePosition); 1792 client.Name, Scene.Name, AbsolutePosition);
1793
1794 m_inTransit = true;
1712 1795
1713 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); // Get this ahead of time because IsInTransit modifies 'm_AgentControlFlags'
1714
1715 IsInTransit = true;
1716 try 1796 try
1717 { 1797 {
1718 // Make sure it's not a login agent. We don't want to wait for updates during login 1798 // Make sure it's not a login agent. We don't want to wait for updates during login
1719 if (!(PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))) 1799 if (!isNPC && !IsRealLogin(m_teleportFlags))
1720 { 1800 {
1801
1721 // Let's wait until UpdateAgent (called by departing region) is done 1802 // Let's wait until UpdateAgent (called by departing region) is done
1722 if (!WaitForUpdateAgent(client)) 1803 if (!WaitForUpdateAgent(client))
1723 // The sending region never sent the UpdateAgent data, we have to refuse 1804 // The sending region never sent the UpdateAgent data, we have to refuse
1724 return; 1805 return;
1725 } 1806 }
1726 1807
1727 Vector3 look = Velocity; 1808 m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1728 1809
1729 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1810 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1730 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) 1811
1812 if (!MakeRootAgent(AbsolutePosition, flying))
1731 { 1813 {
1732 look = new Vector3(0.99f, 0.042f, 0); 1814 m_log.DebugFormat(
1815 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1816 Name, Scene.Name);
1817
1818 return;
1733 } 1819 }
1734 1820
1735 // Prevent teleporting to an underground location 1821 m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1736 // (may crash client otherwise) 1822
1737 // 1823 Vector3 look = Lookat;
1738 Vector3 pos = AbsolutePosition; 1824 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01))
1739 float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
1740 if (pos.Z < ground + 1.5f)
1741 { 1825 {
1742 pos.Z = ground + 1.5f; 1826 look = Velocity;
1743 AbsolutePosition = pos; 1827 look.Z = 0;
1828 look.Normalize();
1829 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) )
1830 look = new Vector3(0.99f, 0.042f, 0);
1744 } 1831 }
1745 1832
1746 if (!MakeRootAgent(AbsolutePosition, flying)) 1833// start sending terrain patchs
1834 if (!isNPC)
1835 Scene.SendLayerData(ControllingClient);
1836
1837 if (!IsChildAgent && !isNPC)
1747 { 1838 {
1748 m_log.DebugFormat( 1839 InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46);
1749 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", 1840 if (cof == null)
1750 Name, Scene.Name); 1841 COF = UUID.Zero;
1842 else
1843 COF = cof.ID;
1751 1844
1752 return; 1845 m_log.DebugFormat("[ScenePresence]: CompleteMovement COF for {0} is {1}", client.AgentId, COF);
1753 } 1846 }
1754 1847
1755 // Tell the client that we're totally ready 1848 // Tell the client that we're totally ready
1756 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1849 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1757 1850
1758 // Child agents send initial data up in LLUDPServer.HandleUseCircuitCode() 1851 m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1759 if (!SentInitialDataToClient)
1760 SendInitialDataToClient();
1761
1762 // m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1763 1852
1764 if (!string.IsNullOrEmpty(m_callbackURI)) 1853 if (!string.IsNullOrEmpty(m_callbackURI))
1765 { 1854 {
@@ -1768,69 +1857,205 @@ namespace OpenSim.Region.Framework.Scenes
1768 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete 1857 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1769 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this 1858 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1770 // region as the current region, meaning that a close sent before then will fail the teleport. 1859 // region as the current region, meaning that a close sent before then will fail the teleport.
1771 // System.Threading.Thread.Sleep(2000); 1860 // System.Threading.Thread.Sleep(2000);
1772 1861
1773 m_log.DebugFormat( 1862 m_log.DebugFormat(
1774 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1863 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1775 client.Name, client.AgentId, m_callbackURI); 1864 client.Name, client.AgentId, m_callbackURI);
1776 1865
1777 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1866 UUID originID;
1867
1868 lock (m_originRegionIDAccessLock)
1869 originID = m_originRegionID;
1870
1871 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1778 m_callbackURI = null; 1872 m_callbackURI = null;
1779 } 1873 }
1780 // else 1874// else
1781 // { 1875// {
1782 // m_log.DebugFormat( 1876// m_log.DebugFormat(
1783 // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", 1877// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1784 // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); 1878// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1785 // } 1879// }
1786 1880
1787 ValidateAndSendAppearanceAndAgentData(); 1881 m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1788 1882
1789 // Create child agents in neighbouring regions 1883 m_previusParcelHide = false;
1790 if (openChildAgents && !IsChildAgent) 1884 m_previusParcelUUID = UUID.Zero;
1885 m_currentParcelHide = false;
1886 m_currentParcelUUID = UUID.Zero;
1887
1888 // send initial land overlay and parcel
1889 ILandChannel landch = m_scene.LandChannel;
1890 if (landch != null)
1891 landch.sendClientInitialLandInfo(client);
1892
1893 if (!IsChildAgent)
1791 { 1894 {
1792 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1895
1793 if (m_agentTransfer != null) 1896 // ValidateAndSendAppearanceAndAgentData();
1897
1898 // do it here in line
1899 // so sequence is clear
1900
1901 // verify baked textures and cache
1902 bool cachedbaked = false;
1903
1904 if (isNPC)
1905 cachedbaked = true;
1906 else
1907 {
1908 if (m_scene.AvatarFactory != null)
1909 cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
1910
1911 // not sure we need this
1912 if (!cachedbaked)
1913 {
1914 if (m_scene.AvatarFactory != null)
1915 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
1916 }
1917 }
1918
1919 List<ScenePresence> allpresences = m_scene.GetScenePresences();
1920
1921 // send avatar object to all presences including us, so they cross it into region
1922 // then hide if necessary
1923 SendInitialAvatarDataToAllAgents(allpresences);
1924
1925 // send this look
1926 SendAppearanceToAgent(this);
1927
1928 // send this animations
1929
1930 UUID[] animIDs = null;
1931 int[] animseqs = null;
1932 UUID[] animsobjs = null;
1933
1934 if (Animator != null)
1935 Animator.GetArrays(out animIDs, out animseqs, out animsobjs);
1936
1937 bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null);
1938
1939 if (haveAnims)
1940 SendAnimPackToAgent(this, animIDs, animseqs, animsobjs);
1941
1942 // we should be able to receive updates, etc
1943 // so release them
1944 m_inTransit = false;
1945
1946 // send look and animations to others
1947 // if not cached we send greys
1948 // uncomented if will wait till avatar does baking
1949 //if (cachedbaked)
1950 {
1951 foreach (ScenePresence p in allpresences)
1952 {
1953 if (p == this)
1954 continue;
1955
1956 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1957 continue;
1958
1959 SendAppearanceToAgentNF(p);
1960 if (haveAnims)
1961 SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs);
1962 }
1963 } // greys if
1964
1965 m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1966
1967 // attachments
1968
1969 if (isNPC || IsRealLogin(m_teleportFlags))
1970 {
1971 if (Scene.AttachmentsModule != null)
1972 // Util.FireAndForget(
1973 // o =>
1974 // {
1975 if (!isNPC)
1976 Scene.AttachmentsModule.RezAttachments(this);
1977 else
1978 Util.FireAndForget(x =>
1979 {
1980 Scene.AttachmentsModule.RezAttachments(this);
1981 });
1982 // });
1983 }
1984 else
1794 { 1985 {
1795 // Note: this call can take a while, because it notifies each of the simulator's neighbours. 1986 if (m_attachments.Count > 0)
1796 // It's important that we don't allow the avatar to cross regions meanwhile, as that will 1987 {
1797 // cause serious errors. We've prevented that from happening by setting IsInTransit=true. 1988 m_log.DebugFormat(
1798 m_agentTransfer.EnableChildAgents(this); 1989 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1990
1991 foreach (SceneObjectGroup sog in m_attachments)
1992 {
1993 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1994 sog.ResumeScripts();
1995 }
1996
1997 foreach (ScenePresence p in allpresences)
1998 {
1999 if (p == this)
2000 {
2001 SendTerseUpdateToAgentNF(this);
2002 SendAttachmentsToAgentNF(this);
2003 continue;
2004 }
2005
2006 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
2007 continue;
2008
2009 SendTerseUpdateToAgentNF(p);
2010 SendAttachmentsToAgentNF(p);
2011 }
2012 }
1799 } 2013 }
1800 2014
2015 m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2016 if (openChildAgents)
2017 {
2018 // Create child agents in neighbouring regions
2019 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
2020 if (m_agentTransfer != null)
2021 {
2022 m_agentTransfer.EnableChildAgents(this);
2023 }
2024 }
2025 }
2026
2027 m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2028
2029 // send the rest of the world
2030 if (m_teleportFlags > 0 && !isNPC || m_currentParcelHide)
2031 SendInitialDataToMe();
2032
2033 m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2034
2035 if (!IsChildAgent && openChildAgents)
2036 {
1801 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 2037 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
1802 if (friendsModule != null) 2038 if (friendsModule != null)
1803 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); 2039 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1804 2040
1805 } 2041 m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1806 2042
1807 // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region 2043 }
1808 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work.
1809 // This may be due to viewer code or it may be something we're not doing properly simulator side.
1810 WorkManager.RunJob(
1811 "ScheduleAttachmentsForFullUpdate",
1812 o => ScheduleAttachmentsForFullUpdate(),
1813 null,
1814 string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name),
1815 true);
1816
1817 // m_log.DebugFormat(
1818 // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1819 // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1820 } 2044 }
1821 finally 2045 finally
1822 { 2046 {
1823 IsInTransit = false; 2047 m_inTransit = false;
1824 } 2048 }
1825 } 2049 // if hide force a check
2050 // if (!IsChildAgent && newhide)
2051 // {
2052 // ParcelLoginCheck(m_currentParcelUUID);
2053 // m_currentParcelHide = newhide;
2054 // }
1826 2055
1827 private void ScheduleAttachmentsForFullUpdate() 2056 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
1828 { 2057
1829 lock (m_attachments) 2058 m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1830 {
1831 foreach (SceneObjectGroup sog in m_attachments)
1832 sog.ScheduleGroupForFullUpdate();
1833 }
1834 } 2059 }
1835 2060
1836 /// <summary> 2061 /// <summary>
@@ -1921,6 +2146,9 @@ namespace OpenSim.Region.Framework.Scenes
1921 return; 2146 return;
1922 } 2147 }
1923 2148
2149 if (IsInTransit)
2150 return;
2151
1924 #region Sanity Checking 2152 #region Sanity Checking
1925 2153
1926 // This is irritating. Really. 2154 // This is irritating. Really.
@@ -1955,8 +2183,8 @@ namespace OpenSim.Region.Framework.Scenes
1955 // When we get to the point of re-computing neighbors everytime this 2183 // When we get to the point of re-computing neighbors everytime this
1956 // changes, then start using the agent's drawdistance rather than the 2184 // changes, then start using the agent's drawdistance rather than the
1957 // region's draw distance. 2185 // region's draw distance.
2186
1958 DrawDistance = agentData.Far; 2187 DrawDistance = agentData.Far;
1959 // DrawDistance = Scene.DefaultDrawDistance;
1960 2188
1961 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; 2189 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
1962 2190
@@ -1964,7 +2192,7 @@ namespace OpenSim.Region.Framework.Scenes
1964 // is first pressed, not whilst it is held down. If this is required in the future then need to look 2192 // is first pressed, not whilst it is held down. If this is required in the future then need to look
1965 // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not 2193 // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not
1966 // received (e.g. on holding LMB down on the avatar in a viewer). 2194 // received (e.g. on holding LMB down on the avatar in a viewer).
1967// m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; 2195 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
1968 2196
1969 #endregion Inputs 2197 #endregion Inputs
1970 2198
@@ -1977,6 +2205,7 @@ namespace OpenSim.Region.Framework.Scenes
1977// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2205// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1978// m_updateCount = UPDATE_COUNT; 2206// m_updateCount = UPDATE_COUNT;
1979 2207
2208
1980 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) 2209 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1981 { 2210 {
1982 StandUp(); 2211 StandUp();
@@ -2032,7 +2261,7 @@ namespace OpenSim.Region.Framework.Scenes
2032 2261
2033 // We need to send this back to the client in order to stop the edit beams 2262 // We need to send this back to the client in order to stop the edit beams
2034 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) 2263 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2035 ControllingClient.SendAgentTerseUpdate(this); 2264 SendAgentTerseUpdate(this);
2036 2265
2037 PhysicsActor actor = PhysicsActor; 2266 PhysicsActor actor = PhysicsActor;
2038 2267
@@ -2045,10 +2274,8 @@ namespace OpenSim.Region.Framework.Scenes
2045 2274
2046 if (AllowMovement && !SitGround) 2275 if (AllowMovement && !SitGround)
2047 { 2276 {
2048// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); 2277// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
2049
2050 bool update_rotation = false; 2278 bool update_rotation = false;
2051
2052 if (agentData.BodyRotation != Rotation) 2279 if (agentData.BodyRotation != Rotation)
2053 { 2280 {
2054 Rotation = agentData.BodyRotation; 2281 Rotation = agentData.BodyRotation;
@@ -2057,14 +2284,6 @@ namespace OpenSim.Region.Framework.Scenes
2057 2284
2058 bool update_movementflag = false; 2285 bool update_movementflag = false;
2059 2286
2060 // If we were just made root agent then we must perform movement updates for the first AgentUpdate that
2061 // we get
2062 if (MovementFlag == ForceUpdateMovementFlagValue)
2063 {
2064 MovementFlag = 0;
2065 update_movementflag = true;
2066 }
2067
2068 if (agentData.UseClientAgentPosition) 2287 if (agentData.UseClientAgentPosition)
2069 { 2288 {
2070 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; 2289 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
@@ -2075,7 +2294,7 @@ namespace OpenSim.Region.Framework.Scenes
2075 bool DCFlagKeyPressed = false; 2294 bool DCFlagKeyPressed = false;
2076 Vector3 agent_control_v3 = Vector3.Zero; 2295 Vector3 agent_control_v3 = Vector3.Zero;
2077 2296
2078 bool newFlying = actor.Flying; 2297 bool newFlying = false;
2079 2298
2080 if (ForceFly) 2299 if (ForceFly)
2081 newFlying = true; 2300 newFlying = true;
@@ -2096,6 +2315,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2315 {
2097 bool bAllowUpdateMoveToPosition = false; 2316 bool bAllowUpdateMoveToPosition = false;
2098 2317
2318 Vector3[] dirVectors;
2319
2320 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
2321 // this prevents 'jumping' in inappropriate situations.
2322// if (!Flying && (m_mouseLook || m_leftButtonDown))
2323// dirVectors = GetWalkDirectionVectors();
2324// else
2325 dirVectors = Dir_Vectors;
2326
2099 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2327 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
2100 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2328 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
2101 { 2329 {
@@ -2105,9 +2333,7 @@ namespace OpenSim.Region.Framework.Scenes
2105 2333
2106 try 2334 try
2107 { 2335 {
2108 // Don't slide against ground when crouching if camera is panned around avatar 2336 agent_control_v3 += Dir_Vectors[i];
2109 if (Flying || DCF != Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN)
2110 agent_control_v3 += Dir_Vectors[i];
2111 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 2337 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);
2112 } 2338 }
2113 catch (IndexOutOfRangeException) 2339 catch (IndexOutOfRangeException)
@@ -2115,10 +2341,10 @@ namespace OpenSim.Region.Framework.Scenes
2115 // Why did I get this? 2341 // Why did I get this?
2116 } 2342 }
2117 2343
2118 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive) 2344 if (((MovementFlag & (uint)DCF) == 0))
2119 { 2345 {
2120 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2346 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
2121 MovementFlag += (uint)DCF; 2347 MovementFlag |= (uint)DCF;
2122 update_movementflag = true; 2348 update_movementflag = true;
2123 } 2349 }
2124 } 2350 }
@@ -2127,7 +2353,7 @@ namespace OpenSim.Region.Framework.Scenes
2127 if ((MovementFlag & (uint)DCF) != 0) 2353 if ((MovementFlag & (uint)DCF) != 0)
2128 { 2354 {
2129 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2355 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
2130 MovementFlag -= (uint)DCF; 2356 MovementFlag &= (uint)~DCF;
2131 update_movementflag = true; 2357 update_movementflag = true;
2132 2358
2133 /* 2359 /*
@@ -2180,11 +2406,11 @@ namespace OpenSim.Region.Framework.Scenes
2180 if (Flying && !ForceFly) 2406 if (Flying && !ForceFly)
2181 { 2407 {
2182 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP 2408 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
2183 if (AgentControlStopActive) 2409 // if (AgentControlStopActive)
2184 { 2410 // {
2185 agent_control_v3 = Vector3.Zero; 2411 // agent_control_v3 = Vector3.Zero;
2186 } 2412 // }
2187 else 2413 // else
2188 { 2414 {
2189 // Landing detection code 2415 // Landing detection code
2190 2416
@@ -2192,38 +2418,44 @@ namespace OpenSim.Region.Framework.Scenes
2192 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || 2418 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
2193 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2419 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2194 2420
2195 //m_log.Debug("[CONTROL]: " +flags); 2421 //m_log.Debug("[CONTROL]: " +flags);
2196 // Applies a satisfying roll effect to the avatar when flying. 2422 // Applies a satisfying roll effect to the avatar when flying.
2197 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) 2423 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2198 { 2424 {
2199 ApplyFlyingRoll( 2425 ApplyFlyingRoll(
2200 FLY_ROLL_RADIANS_PER_UPDATE, 2426 FLY_ROLL_RADIANS_PER_UPDATE,
2201 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 2427 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2202 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); 2428 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2203 } 2429 }
2204 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && 2430 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2205 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2431 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2206 { 2432 {
2207 ApplyFlyingRoll( 2433 ApplyFlyingRoll(
2208 -FLY_ROLL_RADIANS_PER_UPDATE, 2434 -FLY_ROLL_RADIANS_PER_UPDATE,
2209 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 2435 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2210 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); 2436 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2211 } 2437 }
2212 else 2438 else
2213 { 2439 {
2214 if (m_AngularVelocity.Z != 0) 2440 if (m_AngularVelocity.Z != 0)
2215 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); 2441 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2216 }
2217
2218 if (Flying && IsColliding && controlland)
2219 {
2220 // nesting this check because LengthSquared() is expensive and we don't
2221 // want to do it every step when flying.
2222 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2223 StopFlying();
2224 } 2442 }
2443
2444 /*
2445 if (Flying && IsColliding && controlland)
2446 {
2447 // nesting this check because LengthSquared() is expensive and we don't
2448 // want to do it every step when flying.
2449 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2450 StopFlying();
2451 }
2452 */
2225 } 2453 }
2226 } 2454 }
2455 else if (IsColliding && agent_control_v3.Z < 0f)
2456 agent_control_v3.Z = 0;
2457// else if(AgentControlStopActive %% Velocity.Z <0.01f)
2458
2227 2459
2228// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); 2460// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2229 2461
@@ -2236,32 +2468,23 @@ namespace OpenSim.Region.Framework.Scenes
2236 if (update_movementflag 2468 if (update_movementflag
2237 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) 2469 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
2238 { 2470 {
2239// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
2240// {
2241// m_log.DebugFormat(
2242// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2243// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2244// update_movementflag, MovementFlag, update_rotation);
2245
2246 float speedModifier;
2247 2471
2248 if (AgentControlStopActive) 2472 if (AgentControlStopActive)
2249 speedModifier = AgentControlStopSlowWhilstMoving; 2473 {
2474 // if (MovementFlag == 0 && Animator.Falling)
2475 if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2476 {
2477 AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true);
2478 }
2250 else 2479 else
2251 speedModifier = 1; 2480 AddNewMovement(agent_control_v3, AgentControlStopSlowVel);
2481 }
2482 else
2483 {
2484 AddNewMovement(agent_control_v3);
2485 }
2252 2486
2253 AddNewMovement(agent_control_v3, speedModifier);
2254// }
2255 } 2487 }
2256// else
2257// {
2258// if (!update_movementflag)
2259// {
2260// m_log.DebugFormat(
2261// "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
2262// m_scene.RegionInfo.RegionName, agent_control_v3, Name);
2263// }
2264// }
2265 2488
2266 if (update_movementflag && ParentID == 0) 2489 if (update_movementflag && ParentID == 0)
2267 { 2490 {
@@ -2274,7 +2497,7 @@ namespace OpenSim.Region.Framework.Scenes
2274 2497
2275 // We need to send this back to the client in order to see the edit beams 2498 // We need to send this back to the client in order to see the edit beams
2276 if ((State & (uint)AgentState.Editing) != 0) 2499 if ((State & (uint)AgentState.Editing) != 0)
2277 ControllingClient.SendAgentTerseUpdate(this); 2500 SendAgentTerseUpdate(this);
2278 2501
2279 m_scene.EventManager.TriggerOnClientMovement(this); 2502 m_scene.EventManager.TriggerOnClientMovement(this);
2280 } 2503 }
@@ -2320,8 +2543,8 @@ namespace OpenSim.Region.Framework.Scenes
2320 // When we get to the point of re-computing neighbors everytime this 2543 // When we get to the point of re-computing neighbors everytime this
2321 // changes, then start using the agent's drawdistance rather than the 2544 // changes, then start using the agent's drawdistance rather than the
2322 // region's draw distance. 2545 // region's draw distance.
2546
2323 DrawDistance = agentData.Far; 2547 DrawDistance = agentData.Far;
2324 // DrawDistance = Scene.DefaultDrawDistance;
2325 2548
2326 // Check if Client has camera in 'follow cam' or 'build' mode. 2549 // Check if Client has camera in 'follow cam' or 'build' mode.
2327 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); 2550 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
@@ -2358,11 +2581,13 @@ namespace OpenSim.Region.Framework.Scenes
2358 2581
2359 bool updated = false; 2582 bool updated = false;
2360 2583
2584 Vector3 LocalVectorToTarget3D = MoveToPositionTarget - AbsolutePosition;
2585
2361// m_log.DebugFormat( 2586// m_log.DebugFormat(
2362// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 2587// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
2363// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 2588// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
2364 2589
2365 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 2590 double distanceToTarget = LocalVectorToTarget3D.Length();
2366 2591
2367// m_log.DebugFormat( 2592// m_log.DebugFormat(
2368// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", 2593// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
@@ -2385,11 +2610,11 @@ namespace OpenSim.Region.Framework.Scenes
2385 // Theoretically we might need a more complex PID approach here if other 2610 // Theoretically we might need a more complex PID approach here if other
2386 // unknown forces are acting on the avatar and we need to adaptively respond 2611 // unknown forces are acting on the avatar and we need to adaptively respond
2387 // to such forces, but the following simple approach seems to works fine. 2612 // to such forces, but the following simple approach seems to works fine.
2388 Vector3 LocalVectorToTarget3D = 2613
2389 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 2614 LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(Rotation); // change to avatar coords
2390 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords
2391 // Ignore z component of vector 2615 // Ignore z component of vector
2392// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 2616// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
2617
2393 LocalVectorToTarget3D.Normalize(); 2618 LocalVectorToTarget3D.Normalize();
2394 2619
2395 // update avatar movement flags. the avatar coordinate system is as follows: 2620 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -2413,28 +2638,37 @@ namespace OpenSim.Region.Framework.Scenes
2413 2638
2414 // based on the above avatar coordinate system, classify the movement into 2639 // based on the above avatar coordinate system, classify the movement into
2415 // one of left/right/back/forward. 2640 // one of left/right/back/forward.
2641
2642 const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK |
2643 Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT |
2644 Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP |
2645 Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN));
2646
2647 MovementFlag &= noMovFlagsMask;
2648 AgentControlFlags &= noMovFlagsMask;
2649
2416 if (LocalVectorToTarget3D.X < 0) //MoveBack 2650 if (LocalVectorToTarget3D.X < 0) //MoveBack
2417 { 2651 {
2418 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2652 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2419 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2653 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2420 updated = true; 2654 updated = true;
2421 } 2655 }
2422 else if (LocalVectorToTarget3D.X > 0) //Move Forward 2656 else if (LocalVectorToTarget3D.X > 0) //Move Forward
2423 { 2657 {
2424 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2658 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2425 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2659 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2426 updated = true; 2660 updated = true;
2427 } 2661 }
2428 2662
2429 if (LocalVectorToTarget3D.Y > 0) //MoveLeft 2663 if (LocalVectorToTarget3D.Y > 0) //MoveLeft
2430 { 2664 {
2431 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2665 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2432 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2666 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2433 updated = true; 2667 updated = true;
2434 } 2668 }
2435 else if (LocalVectorToTarget3D.Y < 0) //MoveRight 2669 else if (LocalVectorToTarget3D.Y < 0) //MoveRight
2436 { 2670 {
2437 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2671 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2438 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2672 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2439 updated = true; 2673 updated = true;
2440 } 2674 }
@@ -2504,37 +2738,25 @@ namespace OpenSim.Region.Framework.Scenes
2504 || pos.Y < 0 || pos.Y >= regionSize.Y 2738 || pos.Y < 0 || pos.Y >= regionSize.Y
2505 || pos.Z < 0) 2739 || pos.Z < 0)
2506 return; 2740 return;
2507 2741
2508 Scene targetScene = m_scene; 2742 Scene targetScene = m_scene;
2509
2510// Vector3 heightAdjust = new Vector3(0, 0, Appearance.AvatarHeight / 2);
2511// pos += heightAdjust;
2512//
2513// // Anti duck-walking measure
2514// if (Math.Abs(pos.Z - AbsolutePosition.Z) < 0.2f)
2515// {
2516//// m_log.DebugFormat("[SCENE PRESENCE]: Adjusting MoveToPosition from {0} to {1}", pos, AbsolutePosition);
2517// pos.Z = AbsolutePosition.Z;
2518// }
2519
2520 // Get terrain height for sub-region in a megaregion if necessary 2743 // Get terrain height for sub-region in a megaregion if necessary
2521
2522 //COMMENT: If its only nessesary in a megaregion, why do it on normal region's too?
2523
2524 if (regionCombinerModule != null) 2744 if (regionCombinerModule != null)
2525 { 2745 {
2526 int x = (int)((m_scene.RegionInfo.WorldLocX) + pos.X); 2746 int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2527 int y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y); 2747 int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2528 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y); 2748 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2529
2530 // If X and Y is NaN, target_region will be null 2749 // If X and Y is NaN, target_region will be null
2531 if (target_region == null) 2750 if (target_region == null)
2532 return; 2751 return;
2533 2752 UUID target_regionID = target_region.RegionID;
2534 SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene); 2753 SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene);
2535 } 2754 }
2536 2755
2537 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)]; 2756 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2757 // dont try to land underground
2758 terrainHeight += Appearance.AvatarHeight / 2;
2759
2538 pos.Z = Math.Max(terrainHeight, pos.Z); 2760 pos.Z = Math.Max(terrainHeight, pos.Z);
2539 2761
2540 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2762 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2543,17 +2765,14 @@ namespace OpenSim.Region.Framework.Scenes
2543 if (pos.Z - terrainHeight < 0.2) 2765 if (pos.Z - terrainHeight < 0.2)
2544 pos.Z = terrainHeight; 2766 pos.Z = terrainHeight;
2545 2767
2546 if (noFly)
2547 Flying = false;
2548 else if (pos.Z > terrainHeight)
2549 Flying = true;
2550
2551// m_log.DebugFormat( 2768// m_log.DebugFormat(
2552// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 2769// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2553// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 2770// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2554 2771
2555 if (noFly) 2772 if (noFly)
2556 Flying = false; 2773 Flying = false;
2774 else if (pos.Z > terrainHeight + Appearance.AvatarHeight / 2 || Flying)
2775 Flying = true;
2557 2776
2558 LandAtTarget = landAtTarget; 2777 LandAtTarget = landAtTarget;
2559 MovingToTarget = true; 2778 MovingToTarget = true;
@@ -2629,48 +2848,41 @@ namespace OpenSim.Region.Framework.Scenes
2629 } 2848 }
2630 } 2849 }
2631 2850
2851// part.ParentGroup.DeleteAvatar(UUID);
2852
2853 Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
2854 Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation;
2632 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2855 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2633 2856
2634 ParentID = 0; 2857 ParentID = 0;
2635 ParentPart = null; 2858 ParentPart = null;
2636 2859
2637 Quaternion standRotation;
2638
2639 if (part.SitTargetAvatar == UUID) 2860 if (part.SitTargetAvatar == UUID)
2640 { 2861 standRotation = standRotation * part.SitTargetOrientation;
2641 standRotation = part.GetWorldRotation(); 2862 else
2863 standRotation = standRotation * m_bodyRot;
2642 2864
2643 if (!part.IsRoot) 2865 m_bodyRot = standRotation;
2644 standRotation = standRotation * part.SitTargetOrientation; 2866
2645// standRotation = part.RotationOffset * part.SitTargetOrientation; 2867 Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2646// else
2647// standRotation = part.SitTargetOrientation;
2648 2868
2869 float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
2870 if (t > 0)
2871 {
2872 t = 1.0f / (float)Math.Sqrt(t);
2873 standRotationZ.W *= t;
2874 standRotationZ.Z *= t;
2649 } 2875 }
2650 else 2876 else
2651 { 2877 {
2652 standRotation = Rotation; 2878 standRotationZ.W = 1.0f;
2879 standRotationZ.Z = 0f;
2653 } 2880 }
2654 2881
2655 //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2882 Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ;
2656 //Vector3 standPos = ParentPosition;
2657
2658// Vector3 standPositionAdjustment
2659// = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f);
2660 Vector3 adjustmentForSitPosition = OffsetPosition * part.ParentGroup.GroupRotation - SIT_TARGET_ADJUSTMENT * part.GetWorldRotation();
2661
2662 // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than
2663 // hardcoding here.
2664 Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation;
2665 2883
2666 Vector3 standPos = part.ParentGroup.AbsolutePosition + adjustmentForSitPosition + adjustmentForSitPose; 2884 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2667 2885 m_pos = standPos;
2668// m_log.DebugFormat(
2669// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2670// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2671
2672 Rotation = standRotation;
2673 AbsolutePosition = standPos;
2674 } 2886 }
2675 2887
2676 // We need to wait until we have calculated proper stand positions before sitting up the physical 2888 // We need to wait until we have calculated proper stand positions before sitting up the physical
@@ -2680,18 +2892,19 @@ namespace OpenSim.Region.Framework.Scenes
2680 2892
2681 if (satOnObject) 2893 if (satOnObject)
2682 { 2894 {
2683 SendAvatarDataToAllClients();
2684 m_requestedSitTargetID = 0; 2895 m_requestedSitTargetID = 0;
2685
2686 part.RemoveSittingAvatar(this); 2896 part.RemoveSittingAvatar(this);
2687
2688 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2897 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2898
2899 SendAvatarDataToAllAgents();
2689 } 2900 }
2690 2901
2691 else if (PhysicsActor == null) 2902 // reset to default sitAnimation
2692 AddToPhysicalScene(false); 2903 sitAnimation = "SIT";
2904
2905// Animator.TrySetMovementAnimation("STAND");
2906 Animator.SetMovementAnimations("STAND");
2693 2907
2694 Animator.TrySetMovementAnimation("STAND");
2695 TriggerScenePresenceUpdated(); 2908 TriggerScenePresenceUpdated();
2696 } 2909 }
2697 2910
@@ -2739,6 +2952,7 @@ namespace OpenSim.Region.Framework.Scenes
2739 if (part == null) 2952 if (part == null)
2740 return; 2953 return;
2741 2954
2955
2742 if (PhysicsActor != null) 2956 if (PhysicsActor != null)
2743 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2957 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2744 2958
@@ -2746,23 +2960,9 @@ namespace OpenSim.Region.Framework.Scenes
2746 2960
2747 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2961 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2748 { 2962 {
2749// m_log.DebugFormat(
2750// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
2751// Name, part.Name, part.LocalId);
2752
2753 offset = part.SitTargetPosition; 2963 offset = part.SitTargetPosition;
2754 sitOrientation = part.SitTargetOrientation; 2964 sitOrientation = part.SitTargetOrientation;
2755 2965
2756 if (!part.IsRoot)
2757 {
2758 // m_log.DebugFormat("Old sit orient {0}", sitOrientation);
2759 sitOrientation = part.RotationOffset * sitOrientation;
2760 // m_log.DebugFormat("New sit orient {0}", sitOrientation);
2761// m_log.DebugFormat("Old sit offset {0}", offset);
2762 offset = offset * part.RotationOffset;
2763// m_log.DebugFormat("New sit offset {0}", offset);
2764 }
2765
2766 canSit = true; 2966 canSit = true;
2767 } 2967 }
2768 else 2968 else
@@ -2796,40 +2996,30 @@ namespace OpenSim.Region.Framework.Scenes
2796 part.AddSittingAvatar(this); 2996 part.AddSittingAvatar(this);
2797 2997
2798 cameraAtOffset = part.GetCameraAtOffset(); 2998 cameraAtOffset = part.GetCameraAtOffset();
2799
2800 if (!part.IsRoot && cameraAtOffset == Vector3.Zero)
2801 cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset();
2802
2803 bool cameraEyeOffsetFromRootForChild = false;
2804 cameraEyeOffset = part.GetCameraEyeOffset(); 2999 cameraEyeOffset = part.GetCameraEyeOffset();
3000
3001 forceMouselook = part.GetForceMouselook();
2805 3002
2806 if (!part.IsRoot && cameraEyeOffset == Vector3.Zero) 3003 if (!part.IsRoot)
2807 {
2808 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2809 cameraEyeOffsetFromRootForChild = true;
2810 }
2811
2812 if ((cameraEyeOffset != Vector3.Zero && !cameraEyeOffsetFromRootForChild) || cameraAtOffset != Vector3.Zero)
2813 { 3004 {
2814 if (!part.IsRoot) 3005 sitOrientation = part.RotationOffset * sitOrientation;
3006 offset = offset * part.RotationOffset;
3007 offset += part.OffsetPosition;
3008
3009 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
2815 { 3010 {
2816 cameraEyeOffset = cameraEyeOffset * part.RotationOffset; 3011 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3012 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3013 }
3014 else
3015 {
3016 cameraAtOffset = cameraAtOffset * part.RotationOffset;
2817 cameraAtOffset += part.OffsetPosition; 3017 cameraAtOffset += part.OffsetPosition;
3018 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3019 cameraEyeOffset += part.OffsetPosition;
2818 } 3020 }
2819
2820 cameraEyeOffset += part.OffsetPosition;
2821 } 3021 }
2822 3022
2823// m_log.DebugFormat(
2824// "[SCENE PRESENCE]: Using cameraAtOffset {0}, cameraEyeOffset {1} for sit on {2} by {3} in {4}",
2825// cameraAtOffset, cameraEyeOffset, part.Name, Name, Scene.Name);
2826
2827 forceMouselook = part.GetForceMouselook();
2828
2829 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2830 // being sat upon.
2831 offset += part.OffsetPosition;
2832
2833 ControllingClient.SendSitResponse( 3023 ControllingClient.SendSitResponse(
2834 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 3024 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2835 3025
@@ -2862,7 +3052,6 @@ namespace OpenSim.Region.Framework.Scenes
2862 { 3052 {
2863 m_requestedSitTargetID = part.LocalId; 3053 m_requestedSitTargetID = part.LocalId;
2864 m_requestedSitTargetUUID = part.UUID; 3054 m_requestedSitTargetUUID = part.UUID;
2865
2866 } 3055 }
2867 else 3056 else
2868 { 3057 {
@@ -2875,13 +3064,8 @@ namespace OpenSim.Region.Framework.Scenes
2875 // returns false if does not suport so older sit can be tried 3064 // returns false if does not suport so older sit can be tried
2876 public bool PhysicsSit(SceneObjectPart part, Vector3 offset) 3065 public bool PhysicsSit(SceneObjectPart part, Vector3 offset)
2877 { 3066 {
2878// TODO: Pull in these bits
2879 return false;
2880/*
2881 if (part == null || part.ParentGroup.IsAttachment) 3067 if (part == null || part.ParentGroup.IsAttachment)
2882 {
2883 return true; 3068 return true;
2884 }
2885 3069
2886 if ( m_scene.PhysicsScene == null) 3070 if ( m_scene.PhysicsScene == null)
2887 return false; 3071 return false;
@@ -2899,15 +3083,12 @@ namespace OpenSim.Region.Framework.Scenes
2899 return true; 3083 return true;
2900 } 3084 }
2901 3085
2902
2903 // not doing autopilot
2904 m_requestedSitTargetID = 0;
2905
2906 if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0) 3086 if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0)
3087 {
2907 return true; 3088 return true;
3089 }
2908 3090
2909 return false; 3091 return false;
2910*/
2911 } 3092 }
2912 3093
2913 3094
@@ -2952,31 +3133,54 @@ namespace OpenSim.Region.Framework.Scenes
2952 ResetMoveToTarget(); 3133 ResetMoveToTarget();
2953 3134
2954 Velocity = Vector3.Zero; 3135 Velocity = Vector3.Zero;
2955 3136 m_AngularVelocity = Vector3.Zero;
2956 part.AddSittingAvatar(this);
2957 3137
2958 Vector3 cameraAtOffset = part.GetCameraAtOffset(); 3138 Vector3 cameraAtOffset = part.GetCameraAtOffset();
2959 Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); 3139 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2960 bool forceMouselook = part.GetForceMouselook(); 3140 bool forceMouselook = part.GetForceMouselook();
2961 3141
2962 ControllingClient.SendSitResponse( 3142 m_bodyRot = Orientation;
2963 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2964 3143
2965 // not using autopilot 3144 if (!part.IsRoot)
3145 {
3146 Orientation = part.RotationOffset * Orientation;
3147 offset = offset * part.RotationOffset;
3148 offset += part.OffsetPosition;
3149
3150 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3151 {
3152 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3153 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3154 }
3155 else
3156 {
3157 cameraAtOffset = cameraAtOffset * part.RotationOffset;
3158 cameraAtOffset += part.OffsetPosition;
3159 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3160 cameraEyeOffset += part.OffsetPosition;
3161 }
3162 }
2966 3163
2967 Rotation = Orientation;
2968 m_pos = offset; 3164 m_pos = offset;
2969 3165
3166 ControllingClient.SendSitResponse(
3167 part.ParentGroup.UUID, offset, Orientation, true, cameraAtOffset, cameraEyeOffset, forceMouselook);
3168
3169
2970 m_requestedSitTargetID = 0; 3170 m_requestedSitTargetID = 0;
3171 part.AddSittingAvatar(this);
2971 3172
2972 ParentPart = part; 3173 ParentPart = part;
2973 ParentID = part.LocalId; 3174 ParentID = part.LocalId;
2974 if(status == 3) 3175
2975 Animator.TrySetMovementAnimation("SIT_GROUND"); 3176 SendAvatarDataToAllAgents();
3177
3178 if (status == 3)
3179 sitAnimation = "SIT_GROUND";
2976 else 3180 else
2977 Animator.TrySetMovementAnimation("SIT"); 3181 sitAnimation = "SIT";
2978 SendAvatarDataToAllClients();
2979 3182
3183 Animator.SetMovementAnimations("SIT");
2980 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3184 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2981 } 3185 }
2982 3186
@@ -2985,7 +3189,7 @@ namespace OpenSim.Region.Framework.Scenes
2985 if (IsChildAgent) 3189 if (IsChildAgent)
2986 return; 3190 return;
2987 3191
2988 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3192 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2989 3193
2990 if (part != null) 3194 if (part != null)
2991 { 3195 {
@@ -3012,40 +3216,27 @@ namespace OpenSim.Region.Framework.Scenes
3012 3216
3013 //Quaternion result = (sitTargetOrient * vq) * nq; 3217 //Quaternion result = (sitTargetOrient * vq) * nq;
3014 3218
3015 double x, y, z, m1, m2; 3219 double x, y, z, m;
3016 3220
3017 Quaternion r = sitTargetOrient; 3221 Quaternion r = sitTargetOrient;
3018 m1 = r.X * r.X + r.Y * r.Y; 3222 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3019 m2 = r.Z * r.Z + r.W * r.W;
3020
3021 // Rotate the vector <0, 0, 1>
3022 x = 2 * (r.X * r.Z + r.Y * r.W);
3023 y = 2 * (-r.X * r.W + r.Y * r.Z);
3024 z = m2 - m1;
3025 3223
3026 // Set m to be the square of the norm of r. 3224 if (Math.Abs(1.0 - m) > 0.000001)
3027 double m = m1 + m2;
3028
3029 // This constant is emperically determined to be what is used in SL.
3030 // See also http://opensimulator.org/mantis/view.php?id=7096
3031 double offset = 0.05;
3032
3033 // Normally m will be ~ 1, but if someone passed a handcrafted quaternion
3034 // to llSitTarget with values so small that squaring them is rounded off
3035 // to zero, then m could be zero. The result of this floating point
3036 // round off error (causing us to skip this impossible normalization)
3037 // is only 5 cm.
3038 if (m > 0.000001)
3039 { 3225 {
3040 offset /= m; 3226 m = 1.0 / Math.Sqrt(m);
3227 r.X *= (float)m;
3228 r.Y *= (float)m;
3229 r.Z *= (float)m;
3230 r.W *= (float)m;
3041 } 3231 }
3042 3232
3233 x = 2 * (r.X * r.Z + r.Y * r.W);
3234 y = 2 * (-r.X * r.W + r.Y * r.Z);
3235 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3043 Vector3 up = new Vector3((float)x, (float)y, (float)z); 3236 Vector3 up = new Vector3((float)x, (float)y, (float)z);
3044 Vector3 sitOffset = up * (float)offset; 3237 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
3045 3238
3046 // sitOffset is in Avatar Center coordinates: from origin to 'sitTargetPos + SIT_TARGET_ADJUSTMENT'. 3239 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3047 // So, we need to _substract_ it to get to the origin of the Avatar Center.
3048 Vector3 newPos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
3049 Quaternion newRot; 3240 Quaternion newRot;
3050 3241
3051 if (part.IsRoot) 3242 if (part.IsRoot)
@@ -3078,19 +3269,24 @@ namespace OpenSim.Region.Framework.Scenes
3078// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 3269// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
3079 } 3270 }
3080 3271
3272 part.AddSittingAvatar(this);
3081 ParentPart = part; 3273 ParentPart = part;
3082 ParentID = m_requestedSitTargetID; 3274 ParentID = m_requestedSitTargetID;
3083 m_AngularVelocity = Vector3.Zero; 3275 m_AngularVelocity = Vector3.Zero;
3084 Velocity = Vector3.Zero; 3276 Velocity = Vector3.Zero;
3085 RemoveFromPhysicalScene(); 3277 RemoveFromPhysicalScene();
3086 3278
3087 String sitAnimation = "SIT"; 3279 m_requestedSitTargetID = 0;
3280
3281 SendAvatarDataToAllAgents();
3282
3283 sitAnimation = "SIT";
3088 if (!String.IsNullOrEmpty(part.SitAnimation)) 3284 if (!String.IsNullOrEmpty(part.SitAnimation))
3089 { 3285 {
3090 sitAnimation = part.SitAnimation; 3286 sitAnimation = part.SitAnimation;
3091 } 3287 }
3092 Animator.TrySetMovementAnimation(sitAnimation); 3288// Animator.TrySetMovementAnimation(sitAnimation);
3093 SendAvatarDataToAllClients(); 3289 Animator.SetMovementAnimations("SIT");
3094 TriggerScenePresenceUpdated(); 3290 TriggerScenePresenceUpdated();
3095 } 3291 }
3096 } 3292 }
@@ -3102,10 +3298,14 @@ namespace OpenSim.Region.Framework.Scenes
3102 3298
3103// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 3299// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
3104 m_AngularVelocity = Vector3.Zero; 3300 m_AngularVelocity = Vector3.Zero;
3105 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3301 sitAnimation = "SIT_GROUND_CONSTRAINED";
3106 TriggerScenePresenceUpdated(); 3302// Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3303// TriggerScenePresenceUpdated();
3107 SitGround = true; 3304 SitGround = true;
3108 RemoveFromPhysicalScene(); 3305 RemoveFromPhysicalScene();
3306
3307 Animator.SetMovementAnimations("SITGROUND");
3308 TriggerScenePresenceUpdated();
3109 } 3309 }
3110 3310
3111 /// <summary> 3311 /// <summary>
@@ -3129,85 +3329,69 @@ namespace OpenSim.Region.Framework.Scenes
3129 TriggerScenePresenceUpdated(); 3329 TriggerScenePresenceUpdated();
3130 } 3330 }
3131 3331
3332 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
3333 {
3334 Animator.avnChangeAnim(animID, addRemove, sendPack);
3335 }
3336
3337
3338
3132 /// <summary> 3339 /// <summary>
3133 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3340 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
3134 /// </summary> 3341 /// </summary>
3135 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3342 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
3136 /// <param name="thisAddSpeedModifier"> 3343 /// <param name="thisAddSpeedModifier">
3137 /// Optional additional speed modifier for this particular add. Default is 1</param> 3344 /// Optional additional speed modifier for this particular add. Default is 1</param>
3138 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1) 3345 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false)
3139 { 3346 {
3140// m_log.DebugFormat( 3347 // m_log.DebugFormat(
3141// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", 3348 // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3142// vec, Rotation, thisAddSpeedModifier, Name); 3349 // vec, Rotation, thisAddSpeedModifier, Name);
3143 3350
3144 Quaternion rot = Rotation; 3351 // rotate from avatar coord space to world
3145 if (!Flying && PresenceType != PresenceType.Npc) 3352 // for now all controls assume this is only a rotation around Z
3146 { 3353 // if not all checks below need to be done before this rotation
3147 // The only situation in which we care about X and Y is avatar flying. The rest of the time 3354 Vector3 direc = vec * Rotation;
3148 // these parameters are not relevant for determining avatar movement direction and cause issues such
3149 // as wrong walk speed if the camera is rotated.
3150 rot.X = 0;
3151 rot.Y = 0;
3152 rot.Normalize();
3153 }
3154
3155 Vector3 direc = vec * rot;
3156 direc.Normalize(); 3355 direc.Normalize();
3157 3356
3158 if (Flying != FlyingOld) // add for fly velocity control 3357 // mouse look situation ?
3159 {
3160 FlyingOld = Flying; // add for fly velocity control
3161 if (!Flying)
3162 WasFlying = true; // add for fly velocity control
3163 }
3164
3165 if (IsColliding)
3166 WasFlying = false; // add for fly velocity control
3167
3168 if ((vec.Z == 0f) && !Flying) 3358 if ((vec.Z == 0f) && !Flying)
3169 direc.Z = 0f; // Prevent camera WASD up. 3359 direc.Z = 0f; // Prevent camera WASD up.
3170 3360
3361 // odd rescalings
3171 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; 3362 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
3172 3363
3173// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3364 // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
3174 3365
3175 if (PhysicsActor != null) 3366 if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling
3367 && (PhysicsActor == null || !PhysicsActor.PIDHoverActive))
3176 { 3368 {
3177 if (Flying) 3369 if (breaking)
3178 { 3370 direc.Z = -9999f; //hack to tell physics to stop on Z
3371 else
3372 direc = Vector3.Zero;
3373 }
3374 else if (Flying)
3375 {
3376 if (IsColliding && direc.Z < 0)
3377 // landing situation, prevent avatar moving or it may fail to land
3378 // animator will handle this condition and do the land
3379 direc = Vector3.Zero;
3380 else
3179 direc *= 4.0f; 3381 direc *= 4.0f;
3180 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 3382 }
3181 //if (controlland) 3383 else if (IsColliding)
3182 // m_log.Info("[AGENT]: landCommand"); 3384 {
3183 //if (IsColliding) 3385 if (direc.Z > 2.0f) // reinforce jumps
3184 // m_log.Info("[AGENT]: colliding");
3185 //if (Flying && IsColliding && controlland)
3186 //{
3187 // StopFlying();
3188 // m_log.Info("[AGENT]: Stop Flying");
3189 //}
3190 }
3191 if (Animator.Falling && WasFlying) // if falling from flying, disable motion add
3192 { 3386 {
3193 direc *= 0.0f; 3387 direc.Z *= 2.6f;
3194 }
3195 else if (!Flying && IsColliding)
3196 {
3197 if (direc.Z > 2.0f)
3198 {
3199 direc.Z *= 2.6f;
3200
3201 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
3202// Animator.TrySetMovementAnimation("PREJUMP");
3203// Animator.TrySetMovementAnimation("JUMP");
3204 }
3205 } 3388 }
3389 else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation
3390 direc.Z = 0;
3206 } 3391 }
3207 3392
3208// m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); 3393 // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
3209 3394
3210 // TODO: Add the force instead of only setting it to support multiple forces per frame?
3211 m_forceToApply = direc; 3395 m_forceToApply = direc;
3212 Animator.UpdateMovementAnimations(); 3396 Animator.UpdateMovementAnimations();
3213 } 3397 }
@@ -3218,27 +3402,26 @@ namespace OpenSim.Region.Framework.Scenes
3218 3402
3219 public override void Update() 3403 public override void Update()
3220 { 3404 {
3405 const float ROTATION_TOLERANCE = 0.01f;
3406 const float VELOCITY_TOLERANCE = 0.001f;
3407 const float POSITION_TOLERANCE = 0.05f;
3408
3221 if (IsChildAgent == false) 3409 if (IsChildAgent == false)
3222 { 3410 {
3411 CheckForBorderCrossing();
3412
3413 if (IsInTransit)
3414 return;
3415
3223 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3416 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
3224 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3417 // grab the latest PhysicsActor velocity, whereas m_velocity is often
3225 // storing a requested force instead of an actual traveling velocity 3418 // storing a requested force instead of an actual traveling velocity
3226 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn) 3419 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn)
3227 SendAvatarDataToAllClients(); 3420 SendAvatarDataToAllAgents();
3228 3421
3229 // Allow any updates for sitting avatars to that llSetPrimitiveLinkParams() can work for very 3422 if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
3230 // small increments (e.g. sit position adjusters). An alternative may be to eliminate the tolerance 3423 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
3231 // checks on all updates but the ramifications of this would need careful consideration. 3424 !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
3232 bool updateClients
3233 = IsSatOnObject && (Rotation != m_lastRotation || Velocity != m_lastVelocity || m_pos != m_lastPosition);
3234
3235 if (!updateClients)
3236 updateClients
3237 = !Rotation.ApproxEquals(m_lastRotation, Scene.RootRotationUpdateTolerance)
3238 || !Velocity.ApproxEquals(m_lastVelocity, Scene.RootVelocityUpdateTolerance)
3239 || !m_pos.ApproxEquals(m_lastPosition, Scene.RootPositionUpdateTolerance);
3240
3241 if (updateClients)
3242 { 3425 {
3243 SendTerseUpdateToAllClients(); 3426 SendTerseUpdateToAllClients();
3244 3427
@@ -3248,9 +3431,6 @@ namespace OpenSim.Region.Framework.Scenes
3248 m_lastVelocity = Velocity; 3431 m_lastVelocity = Velocity;
3249 } 3432 }
3250 3433
3251 if (Scene.AllowAvatarCrossing)
3252 CheckForBorderCrossing();
3253
3254 CheckForSignificantMovement(); // sends update to the modules. 3434 CheckForSignificantMovement(); // sends update to the modules.
3255 } 3435 }
3256 } 3436 }
@@ -3259,8 +3439,38 @@ namespace OpenSim.Region.Framework.Scenes
3259 3439
3260 #region Update Client(s) 3440 #region Update Client(s)
3261 3441
3442 public void SendUpdateToAgent(ScenePresence p)
3443 {
3444 IClientAPI remoteClient = p.ControllingClient;
3445
3446 if (remoteClient.IsActive)
3447 {
3448 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3449 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3450 m_scene.StatsReporter.AddAgentUpdates(1);
3451 }
3452 }
3453
3454 public void SendFullUpdateToClient(IClientAPI remoteClient)
3455 {
3456 if (remoteClient.IsActive)
3457 {
3458 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3459 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3460 m_scene.StatsReporter.AddAgentUpdates(1);
3461 }
3462 }
3463
3464 // this is diferente from SendTerseUpdateToClient
3465 // this sends bypassing entities updates
3466 public void SendAgentTerseUpdate(ISceneEntity p)
3467 {
3468 ControllingClient.SendAgentTerseUpdate(p);
3469 }
3470
3262 /// <summary> 3471 /// <summary>
3263 /// Sends a location update to the client connected to this scenePresence 3472 /// Sends a location update to the client connected to this scenePresence
3473 /// via entity updates
3264 /// </summary> 3474 /// </summary>
3265 /// <param name="remoteClient"></param> 3475 /// <param name="remoteClient"></param>
3266 public void SendTerseUpdateToClient(IClientAPI remoteClient) 3476 public void SendTerseUpdateToClient(IClientAPI remoteClient)
@@ -3269,31 +3479,7 @@ namespace OpenSim.Region.Framework.Scenes
3269 // server. 3479 // server.
3270 if (remoteClient.IsActive) 3480 if (remoteClient.IsActive)
3271 { 3481 {
3272 if (Scene.RootTerseUpdatePeriod > 1)
3273 {
3274// Console.WriteLine(
3275// "{0} {1} {2} {3} {4} {5} for {6} to {7}",
3276// remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f), Name, remoteClient.Name);
3277 if (remoteClient.AgentId != UUID
3278 && !remoteClient.SceneAgent.IsChildAgent
3279 && m_terseUpdateCount % Scene.RootTerseUpdatePeriod != 0
3280 && !Velocity.ApproxEquals(Vector3.Zero, 0.001f))
3281 {
3282// m_log.DebugFormat("[SCENE PRESENCE]: Discarded update from {0} to {1}, args {2} {3} {4} {5} {6} {7}",
3283// Name, remoteClient.Name, remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f));
3284
3285 return;
3286 }
3287 }
3288
3289 if (Scene.ChildTerseUpdatePeriod > 1
3290 && remoteClient.SceneAgent.IsChildAgent
3291 && m_terseUpdateCount % Scene.ChildTerseUpdatePeriod != 0
3292 && !Velocity.ApproxEquals(Vector3.Zero, 0.001f))
3293 return;
3294
3295 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); 3482 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3296
3297 remoteClient.SendEntityUpdate( 3483 remoteClient.SendEntityUpdate(
3298 this, 3484 this,
3299 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 3485 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
@@ -3303,6 +3489,38 @@ namespace OpenSim.Region.Framework.Scenes
3303 } 3489 }
3304 } 3490 }
3305 3491
3492 public void SendTerseUpdateToAgent(ScenePresence p)
3493 {
3494 IClientAPI remoteClient = p.ControllingClient;
3495
3496 if (!remoteClient.IsActive)
3497 return;
3498
3499 if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200)
3500 return;
3501
3502 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3503 remoteClient.SendEntityUpdate(
3504 this,
3505 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3506 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3507
3508 m_scene.StatsReporter.AddAgentUpdates(1);
3509 }
3510
3511 public void SendTerseUpdateToAgentNF(ScenePresence p)
3512 {
3513 IClientAPI remoteClient = p.ControllingClient;
3514 if (remoteClient.IsActive)
3515 {
3516 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3517 remoteClient.SendEntityUpdate(this,
3518 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3519 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3520 m_scene.StatsReporter.AddAgentUpdates(1);
3521 }
3522 }
3523
3306 3524
3307 // vars to support reduced update frequency when velocity is unchanged 3525 // vars to support reduced update frequency when velocity is unchanged
3308 private Vector3 lastVelocitySentToAllClients = Vector3.Zero; 3526 private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
@@ -3331,10 +3549,6 @@ namespace OpenSim.Region.Framework.Scenes
3331 float speed = Velocity.Length(); 3549 float speed = Velocity.Length();
3332 float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity); 3550 float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity);
3333 3551
3334// m_log.DebugFormat(
3335// "[SCENE PRESENCE]: Delta-v {0}, lastVelocity {1}, Velocity {2} for {3} in {4}",
3336// velocidyDiff, lastVelocitySentToAllClients, Velocity, Name, Scene.Name);
3337
3338 // assuming 5 ms. worst case precision for timer, use 2x that 3552 // assuming 5 ms. worst case precision for timer, use 2x that
3339 // for distance error threshold 3553 // for distance error threshold
3340 float distanceErrorThreshold = speed * 0.01f; 3554 float distanceErrorThreshold = speed * 0.01f;
@@ -3343,18 +3557,13 @@ namespace OpenSim.Region.Framework.Scenes
3343 || Math.Abs(distanceError) > distanceErrorThreshold 3557 || Math.Abs(distanceError) > distanceErrorThreshold
3344 || velocityDiff > 0.01f) // did velocity change from last update? 3558 || velocityDiff > 0.01f) // did velocity change from last update?
3345 { 3559 {
3346// m_log.DebugFormat(
3347// "[SCENE PRESENCE]: Update triggered with speed {0}, distanceError {1}, distanceThreshold {2}, delta-v {3} for {4} in {5}",
3348// speed, distanceError, distanceErrorThreshold, velocidyDiff, Name, Scene.Name);
3349
3350 lastVelocitySentToAllClients = Velocity; 3560 lastVelocitySentToAllClients = Velocity;
3351 lastTerseUpdateToAllClientsTick = currentTick; 3561 lastTerseUpdateToAllClientsTick = currentTick;
3352 lastPositionSentToAllClients = OffsetPosition; 3562 lastPositionSentToAllClients = OffsetPosition;
3353 3563
3354 m_terseUpdateCount++; 3564 // Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
3355 3565// m_scene.ForEachClient(SendTerseUpdateToClient);
3356// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name); 3566 m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
3357 m_scene.ForEachClient(SendTerseUpdateToClient);
3358 } 3567 }
3359 TriggerScenePresenceUpdated(); 3568 TriggerScenePresenceUpdated();
3360 } 3569 }
@@ -3379,36 +3588,41 @@ namespace OpenSim.Region.Framework.Scenes
3379 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); 3588 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
3380 } 3589 }
3381 3590
3382 public void SendInitialDataToClient() 3591 public void SendInitialDataToMe()
3383 { 3592 {
3384 SentInitialDataToClient = true;
3385
3386 // Send all scene object to the new client 3593 // Send all scene object to the new client
3387 WorkManager.RunJob("SendInitialDataToClient", delegate 3594 Util.FireAndForget(delegate
3388 { 3595 {
3389// m_log.DebugFormat(
3390// "[SCENE PRESENCE]: Sending initial data to {0} agent {1} in {2}, tp flags {3}",
3391// IsChildAgent ? "child" : "root", Name, Scene.Name, m_teleportFlags);
3392
3393 // we created a new ScenePresence (a new child agent) in a fresh region. 3596 // we created a new ScenePresence (a new child agent) in a fresh region.
3394 // Request info about all the (root) agents in this region 3597 // Request info about all the (root) agents in this region
3395 // Note: This won't send data *to* other clients in that region (children don't send) 3598 // Note: This won't send data *to* other clients in that region (children don't send)
3396 SendOtherAgentsAvatarDataToClient(); 3599 if (m_teleportFlags <= 0)
3397 SendOtherAgentsAppearanceToClient(); 3600 {
3601 Scene.SendLayerData(ControllingClient);
3398 3602
3603 ILandChannel landch = m_scene.LandChannel;
3604 if (landch != null)
3605 {
3606 landch.sendClientInitialLandInfo(ControllingClient);
3607 }
3608 }
3609
3610 SendOtherAgentsAvatarFullToMe();
3399 EntityBase[] entities = Scene.Entities.GetEntities(); 3611 EntityBase[] entities = Scene.Entities.GetEntities();
3400 foreach (EntityBase e in entities) 3612 foreach (EntityBase e in entities)
3401 { 3613 {
3402 if (e != null && e is SceneObjectGroup) 3614 if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment)
3403 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3615 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
3404 } 3616 }
3405 }, null, string.Format("SendInitialDataToClient ({0} in {1})", Name, Scene.Name), false, true); 3617 });
3406 } 3618 }
3407 3619
3408 /// <summary> 3620 /// <summary>
3409 /// Do everything required once a client completes its movement into a region and becomes 3621 /// Do everything required once a client completes its movement into a region and becomes
3410 /// a root agent. 3622 /// a root agent.
3411 /// </summary> 3623 /// </summary>
3624 ///
3625/* only called from on place, do done inline there
3412 private void ValidateAndSendAppearanceAndAgentData() 3626 private void ValidateAndSendAppearanceAndAgentData()
3413 { 3627 {
3414 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); 3628 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID);
@@ -3422,46 +3636,70 @@ namespace OpenSim.Region.Framework.Scenes
3422 // to see if all the baked textures are already here. 3636 // to see if all the baked textures are already here.
3423 if (m_scene.AvatarFactory != null) 3637 if (m_scene.AvatarFactory != null)
3424 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); 3638 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
3425 3639
3426 // If we aren't using a cached appearance, then clear out the baked textures 3640 // If we aren't using a cached appearance, then clear out the baked textures
3427 if (!cachedappearance) 3641 if (!cachedappearance)
3428 { 3642 {
3429 Appearance.ResetAppearance();
3430 if (m_scene.AvatarFactory != null) 3643 if (m_scene.AvatarFactory != null)
3431 m_scene.AvatarFactory.QueueAppearanceSave(UUID); 3644 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
3432 } 3645 }
3433
3434 // This agent just became root. We are going to tell everyone about it. The process of
3435 // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it
3436 // again here... this comes after the cached appearance check because the avatars
3437 // appearance goes into the avatar update packet
3438 SendAvatarDataToAllClients();
3439 3646
3440 // This invocation always shows up in the viewer logs as an error. Is it needed? 3647 // send avatar object to all viewers so they cross it into region
3441 SendAppearanceToClient(this); 3648 bool newhide = m_currentParcelHide;
3649 m_currentParcelHide = false;
3442 3650
3443 // If we are using the the cached appearance then send it out to everyone 3651 SendAvatarDataToAllAgents();
3444 if (cachedappearance)
3445 {
3446 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
3447 3652
3448 // If the avatars baked textures are all in the cache, then we have a 3653 // now hide
3449 // complete appearance... send it out, if not, then we'll send it when 3654 if (newhide)
3450 // the avatar finishes updating its appearance 3655 {
3451 SendAppearanceToAllOtherClients(); 3656 ParcelLoginCheck(m_currentParcelUUID);
3657 m_currentParcelHide = true;
3452 } 3658 }
3453 }
3454 3659
3455 public void SendAvatarDataToAllClients() 3660 SendAppearanceToAgent(this);
3661
3662 m_inTransit = false;
3663
3664 SendAppearanceToAllOtherAgents();
3665
3666 if(Animator!= null)
3667 Animator.SendAnimPack();
3668 }
3669*/
3670 /// <summary>
3671 /// Send avatar full data appearance and animations for all other root agents to this agent, this agent
3672 /// can be either a child or root
3673 /// </summary>
3674 public void SendOtherAgentsAvatarFullToMe()
3456 { 3675 {
3457 SendAvatarDataToAllClients(true); 3676 int count = 0;
3677 m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
3678 {
3679 // only send information about other root agents
3680 if (p.UUID == UUID)
3681 return;
3682
3683 // get the avatar, then a kill if can't see it
3684 p.SendInitialAvatarDataToAgent(this);
3685
3686 if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodLevel < 200)
3687 return;
3688
3689 p.SendAppearanceToAgentNF(this);
3690 p.SendAnimPackToAgentNF(this);
3691 p.SendAttachmentsToAgentNF(this);
3692 count++;
3693 });
3694
3695 m_scene.StatsReporter.AddAgentUpdates(count);
3458 } 3696 }
3459 3697
3460 /// <summary> 3698 /// <summary>
3461 /// Send this agent's avatar data to all other root and child agents in the scene 3699 /// Send this agent's avatar data to all other root and child agents in the scene
3462 /// This agent must be root. This avatar will receive its own update. 3700 /// This agent must be root. This avatar will receive its own update.
3463 /// </summary> 3701 /// </summary>
3464 public void SendAvatarDataToAllClients(bool full) 3702 public void SendAvatarDataToAllAgents()
3465 { 3703 {
3466 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); 3704 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID);
3467 // only send update from root agents to other clients; children are only "listening posts" 3705 // only send update from root agents to other clients; children are only "listening posts"
@@ -3470,64 +3708,73 @@ namespace OpenSim.Region.Framework.Scenes
3470 m_log.WarnFormat( 3708 m_log.WarnFormat(
3471 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", 3709 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}",
3472 Name, Scene.RegionInfo.RegionName); 3710 Name, Scene.RegionInfo.RegionName);
3473
3474 return; 3711 return;
3475 } 3712 }
3476 3713
3477 m_lastSize = Appearance.AvatarSize; 3714 m_lastSize = Appearance.AvatarSize;
3478
3479 int count = 0; 3715 int count = 0;
3716
3480 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3717 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3481 { 3718 {
3482 if (full) 3719 SendAvatarDataToAgent(scenePresence);
3483 SendAvatarDataToClient(scenePresence);
3484 else
3485 scenePresence.ControllingClient.SendAvatarDataImmediate(this);
3486 count++; 3720 count++;
3487 }); 3721 });
3488 3722
3489 m_scene.StatsReporter.AddAgentUpdates(count); 3723 m_scene.StatsReporter.AddAgentUpdates(count);
3490 } 3724 }
3491 3725 // sends avatar object to all clients so they cross it into region
3492 /// <summary> 3726 // then sends kills to hide
3493 /// Send avatar data for all other root agents to this agent, this agent 3727 public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences)
3494 /// can be either a child or root
3495 /// </summary>
3496 public void SendOtherAgentsAvatarDataToClient()
3497 { 3728 {
3729 m_lastSize = Appearance.AvatarSize;
3498 int count = 0; 3730 int count = 0;
3499 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3731 foreach (ScenePresence p in presences)
3500 { 3732 {
3501 // only send information about other root agents 3733 p.ControllingClient.SendAvatarDataImmediate(this);
3502 if (scenePresence.UUID == UUID) 3734 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3503 return; 3735 // either just kill the object
3504 3736 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3505 scenePresence.SendAvatarDataToClient(this); 3737 // or also attachments viewer may still know about
3506 count++; 3738 SendKillTo(p);
3507 }); 3739 count++;
3508 3740 }
3509 m_scene.StatsReporter.AddAgentUpdates(count); 3741 m_scene.StatsReporter.AddAgentUpdates(count);
3510 } 3742 }
3511 3743
3744 public void SendInitialAvatarDataToAgent(ScenePresence p)
3745 {
3746 p.ControllingClient.SendAvatarDataImmediate(this);
3747 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3748 // either just kill the object
3749 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3750 // or also attachments viewer may still know about
3751 SendKillTo(p);
3752 }
3753
3512 /// <summary> 3754 /// <summary>
3513 /// Send avatar data to an agent. 3755 /// Send avatar data to an agent.
3514 /// </summary> 3756 /// </summary>
3515 /// <param name="avatar"></param> 3757 /// <param name="avatar"></param>
3516 public void SendAvatarDataToClient(ScenePresence avatar) 3758 public void SendAvatarDataToAgent(ScenePresence avatar)
3517 { 3759 {
3518 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToClient from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 3760 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
3519 3761 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3762 return;
3520 avatar.ControllingClient.SendAvatarDataImmediate(this); 3763 avatar.ControllingClient.SendAvatarDataImmediate(this);
3521 Animator.SendAnimPackToClient(avatar.ControllingClient); 3764 }
3765
3766 public void SendAvatarDataToAgentNF(ScenePresence avatar)
3767 {
3768 avatar.ControllingClient.SendAvatarDataImmediate(this);
3522 } 3769 }
3523 3770
3524 /// <summary> 3771 /// <summary>
3525 /// Send this agent's appearance to all other root and child agents in the scene 3772 /// Send this agent's appearance to all other root and child agents in the scene
3526 /// This agent must be root. 3773 /// This agent must be root.
3527 /// </summary> 3774 /// </summary>
3528 public void SendAppearanceToAllOtherClients() 3775 public void SendAppearanceToAllOtherAgents()
3529 { 3776 {
3530// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherClients: {0} {1}", Name, UUID); 3777 // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3531 3778
3532 // only send update from root agents to other clients; children are only "listening posts" 3779 // only send update from root agents to other clients; children are only "listening posts"
3533 if (IsChildAgent) 3780 if (IsChildAgent)
@@ -3538,56 +3785,80 @@ namespace OpenSim.Region.Framework.Scenes
3538 3785
3539 return; 3786 return;
3540 } 3787 }
3541 3788
3542 int count = 0; 3789 int count = 0;
3543 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3790 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3544 { 3791 {
3545 // only send information to other root agents 3792 // only send information to other root agents
3546 if (scenePresence.UUID == UUID) 3793 if (scenePresence.UUID == UUID)
3547 return; 3794 return;
3548
3549 SendAppearanceToClient(scenePresence);
3550 count++;
3551 });
3552 3795
3796 SendAppearanceToAgent(scenePresence);
3797 count++;
3798 });
3553 m_scene.StatsReporter.AddAgentUpdates(count); 3799 m_scene.StatsReporter.AddAgentUpdates(count);
3554 } 3800 }
3555 3801
3556 /// <summary> 3802 public void SendAppearanceToAgent(ScenePresence avatar)
3557 /// Send appearance from all other root agents to this agent. this agent
3558 /// can be either root or child
3559 /// </summary>
3560 public void SendOtherAgentsAppearanceToClient()
3561 { 3803 {
3562// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToClient {0} {1}", Name, UUID); 3804 // m_log.DebugFormat(
3805 // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
3806 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3807 return;
3808 SendAppearanceToAgentNF(avatar);
3809 }
3563 3810
3564 int count = 0; 3811 public void SendAppearanceToAgentNF(ScenePresence avatar)
3565 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3812 {
3566 { 3813 avatar.ControllingClient.SendAppearance(
3567 // only send information about other root agents 3814 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3568 if (scenePresence.UUID == UUID) 3815 }
3569 return;
3570
3571 scenePresence.SendAppearanceToClient(this);
3572 count++;
3573 });
3574 3816
3575 m_scene.StatsReporter.AddAgentUpdates(count); 3817 public void SendAnimPackToAgent(ScenePresence p)
3818 {
3819 if (IsChildAgent || Animator == null)
3820 return;
3821
3822 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3823 return;
3824
3825 Animator.SendAnimPackToClient(p.ControllingClient);
3576 } 3826 }
3577 3827
3578 /// <summary> 3828 public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3579 /// Send appearance data to an agent.
3580 /// </summary>
3581 /// <param name="avatar"></param>
3582 public void SendAppearanceToClient(ScenePresence avatar)
3583 { 3829 {
3584// m_log.DebugFormat( 3830 if (IsChildAgent)
3585// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 3831 return;
3586 3832
3587 avatar.ControllingClient.SendAppearance( 3833 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3588 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3834 return;
3589 3835
3590 3836 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3837 }
3838
3839 public void SendAnimPackToAgentNF(ScenePresence p)
3840 {
3841 if (IsChildAgent || Animator == null)
3842 return;
3843 Animator.SendAnimPackToClient(p.ControllingClient);
3844 }
3845
3846 public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3847 {
3848 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3849 }
3850
3851 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
3852 {
3853 if (IsChildAgent)
3854 return;
3855
3856 m_scene.ForEachScenePresence(delegate(ScenePresence p)
3857 {
3858 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3859 return;
3860 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3861 });
3591 } 3862 }
3592 3863
3593 #endregion 3864 #endregion
@@ -3611,6 +3882,7 @@ namespace OpenSim.Region.Framework.Scenes
3611 m_lastChildAgentUpdatePosition = AbsolutePosition; 3882 m_lastChildAgentUpdatePosition = AbsolutePosition;
3612// m_lastChildAgentUpdateCamPosition = CameraPosition; 3883// m_lastChildAgentUpdateCamPosition = CameraPosition;
3613 3884
3885/* cadu is not used
3614 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3886 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3615 cadu.ActiveGroupID = UUID.Zero.Guid; 3887 cadu.ActiveGroupID = UUID.Zero.Guid;
3616 cadu.AgentID = UUID.Guid; 3888 cadu.AgentID = UUID.Guid;
@@ -3624,6 +3896,7 @@ namespace OpenSim.Region.Framework.Scenes
3624 3896
3625 // Throttles 3897 // Throttles
3626 float multiplier = 1; 3898 float multiplier = 1;
3899
3627 int childRegions = KnownRegionCount; 3900 int childRegions = KnownRegionCount;
3628 if (childRegions != 0) 3901 if (childRegions != 0)
3629 multiplier = 1f / childRegions; 3902 multiplier = 1f / childRegions;
@@ -3634,9 +3907,22 @@ namespace OpenSim.Region.Framework.Scenes
3634 3907
3635 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); 3908 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
3636 cadu.Velocity = Velocity; 3909 cadu.Velocity = Velocity;
3637 3910*/
3638 AgentPosition agentpos = new AgentPosition(); 3911 AgentPosition agentpos = new AgentPosition();
3639 agentpos.CopyFrom(cadu, ControllingClient.SessionId); 3912// agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3913
3914 agentpos.AgentID = new UUID(UUID.Guid);
3915 agentpos.SessionID = ControllingClient.SessionId;
3916
3917 agentpos.Size = Appearance.AvatarSize;
3918
3919 agentpos.Center = CameraPosition;
3920 agentpos.Far = DrawDistance;
3921 agentpos.Position = AbsolutePosition;
3922 agentpos.Velocity = Velocity;
3923 agentpos.RegionHandle = RegionHandle;
3924 agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
3925
3640 3926
3641 // Let's get this out of the update loop 3927 // Let's get this out of the update loop
3642 Util.FireAndForget( 3928 Util.FireAndForget(
@@ -3657,7 +3943,7 @@ namespace OpenSim.Region.Framework.Scenes
3657 protected void CheckForBorderCrossing() 3943 protected void CheckForBorderCrossing()
3658 { 3944 {
3659 // Check that we we are not a child 3945 // Check that we we are not a child
3660 if (IsChildAgent) 3946 if (IsChildAgent || IsInTransit)
3661 return; 3947 return;
3662 3948
3663 // If we don't have a PhysActor, we can't cross anyway 3949 // If we don't have a PhysActor, we can't cross anyway
@@ -3667,79 +3953,67 @@ namespace OpenSim.Region.Framework.Scenes
3667 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) 3953 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3668 return; 3954 return;
3669 3955
3670 if (IsInTransit)
3671 return;
3672
3673 Vector3 pos2 = AbsolutePosition; 3956 Vector3 pos2 = AbsolutePosition;
3674 Vector3 origPosition = pos2;
3675 Vector3 vel = Velocity; 3957 Vector3 vel = Velocity;
3676 3958
3677 // Compute the future avatar position. 3959 float timeStep = 0.1f;
3678 // If the avatar will be crossing, we force the crossing to happen now 3960 pos2.X += vel.X * timeStep;
3679 // in the hope that this will make the avatar movement smoother when crossing. 3961 pos2.Y += vel.Y * timeStep;
3680 pos2 += vel * 0.05f; 3962 pos2.Z += vel.Z * timeStep;
3681
3682 if (m_scene.PositionIsInCurrentRegion(pos2))
3683 return;
3684
3685 m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}",
3686 LogHeader, Name, Scene.Name, pos2);
3687 3963
3688 // Disconnect from the current region 3964// m_log.DebugFormat(
3689 bool isFlying = Flying; 3965// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3690 RemoveFromPhysicalScene(); 3966// pos2, Name, Scene.Name);
3691 3967
3692 // pos2 is the forcasted position so make that the 'current' position so the crossing 3968 if (Scene.PositionIsInCurrentRegion(pos2))
3693 // code will move us into the newly addressed region. 3969 return;
3694 m_pos = pos2;
3695 3970
3696 if (CrossToNewRegion()) 3971 if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
3697 {
3698 AddToPhysicalScene(isFlying);
3699 }
3700 else
3701 { 3972 {
3702 // Tried to make crossing happen but it failed. 3973 // we don't have entity transfer module
3703 if (m_requestedSitTargetUUID == UUID.Zero) 3974 Vector3 pos = AbsolutePosition;
3704 { 3975 float px = pos.X;
3705 m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader); 3976 if (px < 0)
3706 3977 pos.X += Velocity.X * 2;
3707 Velocity = Vector3.Zero; 3978 else if (px > m_scene.RegionInfo.RegionSizeX)
3708 AbsolutePosition = EnforceSanityOnPosition(origPosition); 3979 pos.X -= Velocity.X * 2;
3980
3981 float py = pos.Y;
3982 if (py < 0)
3983 pos.Y += Velocity.Y * 2;
3984 else if (py > m_scene.RegionInfo.RegionSizeY)
3985 pos.Y -= Velocity.Y * 2;
3709 3986
3710 AddToPhysicalScene(isFlying); 3987 Velocity = Vector3.Zero;
3711 } 3988 AbsolutePosition = pos;
3712 } 3989 }
3713 } 3990 }
3714 3991
3715 // Given a position, make sure it is within the current region. 3992 public void CrossToNewRegionFail()
3716 // If just outside some border, the returned position will be just inside the border on that side.
3717 private Vector3 EnforceSanityOnPosition(Vector3 origPosition)
3718 { 3993 {
3719 const float borderFudge = 0.1f; 3994 if (m_requestedSitTargetUUID == UUID.Zero)
3720 Vector3 ret = origPosition;
3721
3722 // Sanity checking on the position to make sure it is in the region we couldn't cross from
3723 float extentX = (float)m_scene.RegionInfo.RegionSizeX;
3724 float extentY = (float)m_scene.RegionInfo.RegionSizeY;
3725 IRegionCombinerModule combiner = m_scene.RequestModuleInterface<IRegionCombinerModule>();
3726 if (combiner != null)
3727 { 3995 {
3728 // If a mega-region, the size could be much bigger 3996 bool isFlying = Flying;
3729 Vector2 megaExtent = combiner.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 3997 RemoveFromPhysicalScene();
3730 extentX = megaExtent.X; 3998
3731 extentY = megaExtent.Y; 3999 Vector3 pos = AbsolutePosition;
3732 } 4000 float px = pos.X;
3733 if (ret.X < 0) 4001 if (px < 0)
3734 ret.X = borderFudge; 4002 pos.X += Velocity.X * 2;
3735 else if (ret.X >= extentX) 4003 else if (px > m_scene.RegionInfo.RegionSizeX)
3736 ret.X = extentX - borderFudge; 4004 pos.X -= Velocity.X * 2;
3737 if (ret.Y < 0) 4005
3738 ret.Y = borderFudge; 4006 float py = pos.Y;
3739 else if (ret.Y >= extentY) 4007 if (py < 0)
3740 ret.Y = extentY - borderFudge; 4008 pos.Y += Velocity.Y * 2;
4009 else if (py > m_scene.RegionInfo.RegionSizeY)
4010 pos.Y -= Velocity.Y * 2;
3741 4011
3742 return ret; 4012 Velocity = Vector3.Zero;
4013 AbsolutePosition = pos;
4014
4015 AddToPhysicalScene(isFlying);
4016 }
3743 } 4017 }
3744 4018
3745 /// <summary> 4019 /// <summary>
@@ -3750,27 +4024,36 @@ namespace OpenSim.Region.Framework.Scenes
3750 /// </summary> 4024 /// </summary>
3751 protected bool CrossToNewRegion() 4025 protected bool CrossToNewRegion()
3752 { 4026 {
4027 bool result = false;
4028// parcelRegionCross(false);
3753 try 4029 try
3754 { 4030 {
3755 return m_scene.CrossAgentToNewRegion(this, Flying); 4031 result = m_scene.CrossAgentToNewRegion(this, Flying);
3756 } 4032 }
3757 catch 4033 catch
3758 { 4034 {
3759 return m_scene.CrossAgentToNewRegion(this, false); 4035// result = m_scene.CrossAgentToNewRegion(this, false);
4036 return false;
3760 } 4037 }
3761 } 4038 // if(!result)
3762 4039 // parcelRegionCross(true);
3763 public void Reset()
3764 {
3765// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
3766 4040
3767 // Put the child agent back at the center 4041 return result;
3768 AbsolutePosition
3769 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
3770 4042
3771 Animator.ResetAnimations();
3772 } 4043 }
3773 4044
4045 /* useless. Either use MakeChild or delete the presence
4046 public void Reset()
4047 {
4048 // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
4049
4050 // Put the child agent back at the center
4051 AbsolutePosition
4052 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
4053
4054 Animator.ResetAnimations();
4055 }
4056 */
3774 /// <summary> 4057 /// <summary>
3775 /// Computes which child agents to close when the scene presence moves to another region. 4058 /// Computes which child agents to close when the scene presence moves to another region.
3776 /// Removes those regions from m_knownRegions. 4059 /// Removes those regions from m_knownRegions.
@@ -3778,34 +4061,63 @@ namespace OpenSim.Region.Framework.Scenes
3778 /// <param name="newRegionX">The new region's x on the map</param> 4061 /// <param name="newRegionX">The new region's x on the map</param>
3779 /// <param name="newRegionY">The new region's y on the map</param> 4062 /// <param name="newRegionY">The new region's y on the map</param>
3780 /// <returns></returns> 4063 /// <returns></returns>
3781 public void CloseChildAgents(uint newRegionX, uint newRegionY) 4064 public void CloseChildAgents(bool logout, ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY)
3782 { 4065 {
4066 uint newRegionX, newRegionY;
3783 List<ulong> byebyeRegions = new List<ulong>(); 4067 List<ulong> byebyeRegions = new List<ulong>();
3784 List<ulong> knownRegions = KnownRegionHandles; 4068 List<ulong> knownRegions = KnownRegionHandles;
3785 m_log.DebugFormat( 4069 m_log.DebugFormat(
3786 "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", 4070 "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
3787 knownRegions.Count, Scene.RegionInfo.RegionName); 4071 knownRegions.Count, Scene.RegionInfo.RegionName);
3788 //DumpKnownRegions(); 4072 //DumpKnownRegions();
3789 4073
4074 Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY);
4075
4076 uint x, y;
4077 spRegionSizeInfo regInfo;
4078
4079 // this should not be here
4080 IEventQueue eventQueue = Scene.RequestModuleInterface<IEventQueue>();
4081
3790 foreach (ulong handle in knownRegions) 4082 foreach (ulong handle in knownRegions)
3791 { 4083 {
3792 // Don't close the agent on this region yet 4084 // Don't close the agent on this region yet
3793 if (handle != Scene.RegionInfo.RegionHandle) 4085 if (handle != Scene.RegionInfo.RegionHandle)
3794 { 4086 {
3795 uint x, y; 4087 if (logout)
3796 Util.RegionHandleToRegionLoc(handle, out x, out y);
3797
3798// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
3799// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
3800 float dist = (float)Math.Max(Scene.DefaultDrawDistance,
3801 (float)Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
3802 if (Util.IsOutsideView(dist, x, newRegionX, y, newRegionY))
3803 {
3804 byebyeRegions.Add(handle); 4088 byebyeRegions.Add(handle);
4089 else
4090 {
4091 Util.RegionHandleToRegionLoc(handle, out x, out y);
4092 if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo))
4093 {
4094
4095 // m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
4096 // m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
4097 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY,
4098 regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY))
4099 {
4100 byebyeRegions.Add(handle);
4101 // this should not be here
4102 if(eventQueue != null)
4103 eventQueue.DisableSimulator(handle,UUID);
4104 }
4105 }
4106 else
4107 {
4108 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY,
4109 (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY))
4110 {
4111 byebyeRegions.Add(handle);
4112 // this should not be here
4113 if(eventQueue != null)
4114 eventQueue.DisableSimulator(handle,UUID);
4115 }
4116 }
3805 } 4117 }
3806 } 4118 }
3807 } 4119 }
3808 4120
3809 if (byebyeRegions.Count > 0) 4121 if (byebyeRegions.Count > 0)
3810 { 4122 {
3811 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 4123 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
@@ -3814,12 +4126,13 @@ namespace OpenSim.Region.Framework.Scenes
3814 string auth = string.Empty; 4126 string auth = string.Empty;
3815 if (acd != null) 4127 if (acd != null)
3816 auth = acd.SessionID.ToString(); 4128 auth = acd.SessionID.ToString();
3817 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); 4129 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3818 } 4130 }
3819 4131
3820 foreach (ulong handle in byebyeRegions) 4132 foreach (ulong handle in byebyeRegions)
3821 { 4133 {
3822 RemoveNeighbourRegion(handle); 4134 RemoveNeighbourRegion(handle);
4135 Scene.CapsModule.DropChildSeed(UUID, handle);
3823 } 4136 }
3824 } 4137 }
3825 4138
@@ -3831,6 +4144,8 @@ namespace OpenSim.Region.Framework.Scenes
3831 /// </summary> 4144 /// </summary>
3832 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) 4145 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
3833 { 4146 {
4147 int oldgodlevel = GodLevel;
4148
3834 if (godStatus) 4149 if (godStatus)
3835 { 4150 {
3836 // For now, assign god level 200 to anyone 4151 // For now, assign god level 200 to anyone
@@ -3851,6 +4166,9 @@ namespace OpenSim.Region.Framework.Scenes
3851 } 4166 }
3852 4167
3853 ControllingClient.SendAdminResponse(token, (uint)GodLevel); 4168 ControllingClient.SendAdminResponse(token, (uint)GodLevel);
4169
4170 if(oldgodlevel != GodLevel)
4171 parcelGodCheck(m_currentParcelUUID, GodLevel >= 200);
3854 } 4172 }
3855 4173
3856 #region Child Agent Updates 4174 #region Child Agent Updates
@@ -3862,12 +4180,16 @@ namespace OpenSim.Region.Framework.Scenes
3862 return; 4180 return;
3863 4181
3864 CopyFrom(cAgentData); 4182 CopyFrom(cAgentData);
3865 4183
3866 m_updateAgentReceivedAfterTransferEvent.Set();
3867 } 4184 }
3868 4185
3869 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 4186 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3870 4187
4188 private void RaiseUpdateThrottles()
4189 {
4190 m_scene.EventManager.TriggerThrottleUpdate(this);
4191 }
4192
3871 /// <summary> 4193 /// <summary>
3872 /// This updates important decision making data about a child agent 4194 /// This updates important decision making data about a child agent
3873 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 4195 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
@@ -3877,23 +4199,15 @@ namespace OpenSim.Region.Framework.Scenes
3877 if (!IsChildAgent) 4199 if (!IsChildAgent)
3878 return; 4200 return;
3879 4201
3880// m_log.DebugFormat( 4202 RegionHandle = cAgentData.RegionHandle;
3881// "[SCENE PRESENCE]: ChildAgentPositionUpdate for {0} in {1}, tRegion {2},{3}, rRegion {4},{5}, pos {6}",
3882// Name, Scene.Name, tRegionX, tRegionY, rRegionX, rRegionY, cAgentData.Position);
3883 4203
3884 // Find the distance (in meters) between the two regions 4204 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3885 // XXX: We cannot use Util.RegionLocToHandle() here because a negative value will silently overflow the 4205 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
3886 // uint 4206 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
3887 int shiftx = (int)(((int)rRegionX - (int)tRegionX) * Constants.RegionSize);
3888 int shifty = (int)(((int)rRegionY - (int)tRegionY) * Constants.RegionSize);
3889 4207
3890 Vector3 offset = new Vector3(shiftx, shifty, 0f); 4208 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3891 4209
3892 // When we get to the point of re-computing neighbors everytime this
3893 // changes, then start using the agent's drawdistance rather than the
3894 // region's draw distance.
3895 DrawDistance = cAgentData.Far; 4210 DrawDistance = cAgentData.Far;
3896 // DrawDistance = Scene.DefaultDrawDistance;
3897 4211
3898 if (cAgentData.Position != marker) // UGH!! 4212 if (cAgentData.Position != marker) // UGH!!
3899 m_pos = cAgentData.Position + offset; 4213 m_pos = cAgentData.Position + offset;
@@ -3907,10 +4221,36 @@ namespace OpenSim.Region.Framework.Scenes
3907 CameraPosition = cAgentData.Center + offset; 4221 CameraPosition = cAgentData.Center + offset;
3908 4222
3909 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) 4223 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
3910 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); 4224 {
4225 // some scaling factor
4226 float x = m_pos.X;
4227 if (x > m_scene.RegionInfo.RegionSizeX)
4228 x -= m_scene.RegionInfo.RegionSizeX;
4229 float y = m_pos.Y;
4230 if (y > m_scene.RegionInfo.RegionSizeY)
4231 y -= m_scene.RegionInfo.RegionSizeY;
4232
4233 x = x * x + y * y;
4234
4235 const float distScale = 0.4f / Constants.RegionSize / Constants.RegionSize;
4236 float factor = 1.0f - distScale * x;
4237 if (factor < 0.2f)
4238 factor = 0.2f;
4239
4240 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles,factor);
4241 }
4242
4243 if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0)
4244 {
4245 if (Scene.CapsModule != null)
4246 {
4247 Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds);
4248 }
4249
4250 KnownRegions = cAgentData.ChildrenCapSeeds;
4251 }
3911 4252
3912 //cAgentData.AVHeight; 4253 //cAgentData.AVHeight;
3913 RegionHandle = cAgentData.RegionHandle;
3914 //m_velocity = cAgentData.Velocity; 4254 //m_velocity = cAgentData.Velocity;
3915 } 4255 }
3916 4256
@@ -3932,16 +4272,7 @@ namespace OpenSim.Region.Framework.Scenes
3932 cAgent.Far = DrawDistance; 4272 cAgent.Far = DrawDistance;
3933 4273
3934 // Throttles 4274 // Throttles
3935 float multiplier = 1; 4275 cAgent.Throttles = ControllingClient.GetThrottlesPacked(1);
3936 int childRegions = KnownRegionCount;
3937 if (childRegions != 0)
3938 multiplier = 1f / childRegions;
3939
3940 // Minimum throttle for a child region is 1/4 of the root region throttle
3941 if (multiplier <= 0.25f)
3942 multiplier = 0.25f;
3943
3944 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
3945 4276
3946 cAgent.HeadRotation = m_headrotation; 4277 cAgent.HeadRotation = m_headrotation;
3947 cAgent.BodyRotation = Rotation; 4278 cAgent.BodyRotation = Rotation;
@@ -3954,7 +4285,8 @@ namespace OpenSim.Region.Framework.Scenes
3954 4285
3955 cAgent.AlwaysRun = SetAlwaysRun; 4286 cAgent.AlwaysRun = SetAlwaysRun;
3956 4287
3957 cAgent.Appearance = new AvatarAppearance(Appearance); 4288 // make clear we want the all thing
4289 cAgent.Appearance = new AvatarAppearance(Appearance,true,true);
3958 4290
3959 cAgent.ParentPart = ParentUUID; 4291 cAgent.ParentPart = ParentUUID;
3960 cAgent.SitOffset = PrevSitOffset; 4292 cAgent.SitOffset = PrevSitOffset;
@@ -3980,6 +4312,10 @@ namespace OpenSim.Region.Framework.Scenes
3980 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 4312 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3981 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; 4313 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3982 4314
4315 cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs();
4316
4317 cAgent.MotionState = (byte)Animator.currentControlState;
4318
3983 if (Scene.AttachmentsModule != null) 4319 if (Scene.AttachmentsModule != null)
3984 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 4320 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
3985 } 4321 }
@@ -4004,7 +4340,16 @@ namespace OpenSim.Region.Framework.Scenes
4004 // changes, then start using the agent's drawdistance rather than the 4340 // changes, then start using the agent's drawdistance rather than the
4005 // region's draw distance. 4341 // region's draw distance.
4006 DrawDistance = cAgent.Far; 4342 DrawDistance = cAgent.Far;
4007 // DrawDistance = Scene.DefaultDrawDistance; 4343 //DrawDistance = Scene.DefaultDrawDistance;
4344
4345 if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0)
4346 {
4347 if (Scene.CapsModule != null)
4348 {
4349 Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds);
4350 }
4351 KnownRegions = cAgent.ChildrenCapSeeds;
4352 }
4008 4353
4009 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) 4354 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
4010 ControllingClient.SetChildAgentThrottle(cAgent.Throttles); 4355 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
@@ -4017,14 +4362,17 @@ namespace OpenSim.Region.Framework.Scenes
4017 GodLevel = cAgent.GodLevel; 4362 GodLevel = cAgent.GodLevel;
4018 SetAlwaysRun = cAgent.AlwaysRun; 4363 SetAlwaysRun = cAgent.AlwaysRun;
4019 4364
4365
4020 Appearance = new AvatarAppearance(cAgent.Appearance); 4366 Appearance = new AvatarAppearance(cAgent.Appearance);
4367/*
4368 bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
4369
4021 if (PhysicsActor != null) 4370 if (PhysicsActor != null)
4022 { 4371 {
4023 bool isFlying = Flying;
4024 RemoveFromPhysicalScene(); 4372 RemoveFromPhysicalScene();
4025 AddToPhysicalScene(isFlying); 4373 AddToPhysicalScene(isFlying);
4026 } 4374 }
4027 4375*/
4028 try 4376 try
4029 { 4377 {
4030 lock (scriptedcontrols) 4378 lock (scriptedcontrols)
@@ -4048,34 +4396,23 @@ namespace OpenSim.Region.Framework.Scenes
4048 } 4396 }
4049 catch { } 4397 catch { }
4050 4398
4399 Animator.ResetAnimations();
4400
4401 Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides);
4402
4051 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 4403 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
4052 if (cAgent.Anims != null)
4053 Animator.Animations.FromArray(cAgent.Anims);
4054 if (cAgent.DefaultAnim != null) 4404 if (cAgent.DefaultAnim != null)
4055 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 4405 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
4056 if (cAgent.AnimState != null) 4406 if (cAgent.AnimState != null)
4057 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); 4407 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
4408 if (cAgent.Anims != null)
4409 Animator.Animations.FromArray(cAgent.Anims);
4410 if (cAgent.MotionState != 0)
4411 Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState;
4058 4412
4059 if (Scene.AttachmentsModule != null) 4413 if (Scene.AttachmentsModule != null)
4060 { 4414 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4061 // If the JobEngine is running we can schedule this job now and continue rather than waiting for all 4415
4062 // attachments to copy, which might take a long time in the Hypergrid case as the entire inventory
4063 // graph is inspected for each attachments and assets possibly fetched.
4064 //
4065 // We don't need to worry about a race condition as the job to later start the scripts is also
4066 // JobEngine scheduled and so will always occur after this task.
4067 // XXX: This will not be true if JobEngine ever gets more than one thread.
4068 WorkManager.RunJob(
4069 "CopyAttachments",
4070 o => Scene.AttachmentsModule.CopyAttachments(cAgent, this),
4071 null,
4072 string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name),
4073 true);
4074 }
4075
4076 // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread
4077 // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart
4078 // script attachments can outrace this thread.
4079 lock (m_originRegionIDAccessLock) 4416 lock (m_originRegionIDAccessLock)
4080 m_originRegionID = cAgent.RegionID; 4417 m_originRegionID = cAgent.RegionID;
4081 } 4418 }
@@ -4094,6 +4431,8 @@ namespace OpenSim.Region.Framework.Scenes
4094 /// </summary> 4431 /// </summary>
4095 public void UpdateMovement() 4432 public void UpdateMovement()
4096 { 4433 {
4434 if (IsInTransit)
4435 return;
4097 if (m_forceToApply.HasValue) 4436 if (m_forceToApply.HasValue)
4098 { 4437 {
4099 Vector3 force = m_forceToApply.Value; 4438 Vector3 force = m_forceToApply.Value;
@@ -4124,17 +4463,14 @@ namespace OpenSim.Region.Framework.Scenes
4124 if (Appearance.AvatarHeight == 0) 4463 if (Appearance.AvatarHeight == 0)
4125// Appearance.SetHeight(); 4464// Appearance.SetHeight();
4126 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f)); 4465 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f));
4127
4128/*
4129 PhysicsActor = scene.AddAvatar(
4130 LocalId, Firstname + "." + Lastname, pVec,
4131 new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying);
4132*/
4133 4466
4134 PhysicsActor = m_scene.PhysicsScene.AddAvatar( 4467 PhysicsScene scene = m_scene.PhysicsScene;
4135 LocalId, Firstname + "." + Lastname, AbsolutePosition, Velocity, 4468 Vector3 pVec = AbsolutePosition;
4136 Appearance.AvatarBoxSize, isFlying);
4137 4469
4470 PhysicsActor = scene.AddAvatar(
4471 LocalId, Firstname + "." + Lastname, pVec,
4472 Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying);
4473 PhysicsActor.Orientation = m_bodyRot;
4138 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 4474 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
4139 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 4475 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
4140 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 4476 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
@@ -4168,7 +4504,9 @@ namespace OpenSim.Region.Framework.Scenes
4168 { 4504 {
4169 if (IsChildAgent || Animator == null) 4505 if (IsChildAgent || Animator == null)
4170 return; 4506 return;
4171 4507
4508 if(IsInTransit)
4509 return;
4172 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 4510 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
4173 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( 4511 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
4174 // as of this comment the interval is set in AddToPhysicalScene 4512 // as of this comment the interval is set in AddToPhysicalScene
@@ -4192,7 +4530,49 @@ namespace OpenSim.Region.Framework.Scenes
4192// m_lastColCount = coldata.Count; 4530// m_lastColCount = coldata.Count;
4193// } 4531// }
4194 4532
4195 CollisionPlane = Vector4.UnitW; 4533 if (coldata.Count != 0)
4534 {
4535/*
4536 switch (Animator.CurrentMovementAnimation)
4537 {
4538 case "STAND":
4539 case "WALK":
4540 case "RUN":
4541 case "CROUCH":
4542 case "CROUCHWALK":
4543 {
4544 */
4545 ContactPoint lowest;
4546 lowest.SurfaceNormal = Vector3.Zero;
4547 lowest.Position = Vector3.Zero;
4548 lowest.Position.Z = float.MaxValue;
4549
4550 foreach (ContactPoint contact in coldata.Values)
4551 {
4552
4553 if (contact.CharacterFeet && contact.Position.Z < lowest.Position.Z)
4554 {
4555 lowest = contact;
4556 }
4557 }
4558
4559 if (lowest.Position.Z != float.MaxValue)
4560 {
4561 lowest.SurfaceNormal = -lowest.SurfaceNormal;
4562 CollisionPlane = new Vector4(lowest.SurfaceNormal, Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
4563 }
4564 else
4565 CollisionPlane = Vector4.UnitW;
4566/*
4567 }
4568 break;
4569 }
4570*/
4571 }
4572 else
4573 CollisionPlane = Vector4.UnitW;
4574
4575 RaiseCollisionScriptEvents(coldata);
4196 4576
4197 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 4577 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
4198 if (Invulnerable || GodLevel > 0) 4578 if (Invulnerable || GodLevel > 0)
@@ -4311,6 +4691,10 @@ namespace OpenSim.Region.Framework.Scenes
4311 4691
4312 m_attachments.Add(gobj); 4692 m_attachments.Add(gobj);
4313 } 4693 }
4694
4695 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
4696 if (bakedModule != null)
4697 bakedModule.UpdateMeshAvatar(m_uuid);
4314 } 4698 }
4315 4699
4316 /// <summary> 4700 /// <summary>
@@ -4474,6 +4858,287 @@ namespace OpenSim.Region.Framework.Scenes
4474 return validated; 4858 return validated;
4475 } 4859 }
4476 4860
4861 public void SendAttachmentsToAllAgents()
4862 {
4863 lock (m_attachments)
4864 {
4865 foreach (SceneObjectGroup sog in m_attachments)
4866 {
4867 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4868 {
4869 if (p != this && sog.HasPrivateAttachmentPoint)
4870 return;
4871
4872 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4873 return;
4874
4875 SendTerseUpdateToAgentNF(p);
4876 SendAttachmentFullUpdateToAgentNF(sog, p);
4877 });
4878 }
4879 }
4880 }
4881
4882 // send attachments to a client without filters except for huds
4883 // for now they are checked in several places down the line...
4884 public void SendAttachmentsToAgentNF(ScenePresence p)
4885 {
4886 SendTerseUpdateToAgentNF(p);
4887 lock (m_attachments)
4888 {
4889 foreach (SceneObjectGroup sog in m_attachments)
4890 {
4891 SendAttachmentFullUpdateToAgentNF(sog, p);
4892 }
4893 }
4894 }
4895
4896 public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p)
4897 {
4898 if (p != this && sog.HasPrivateAttachmentPoint)
4899 return;
4900
4901 SceneObjectPart[] parts = sog.Parts;
4902 SceneObjectPart rootpart = sog.RootPart;
4903
4904 p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate);
4905
4906 for (int i = 0; i < parts.Length; i++)
4907 {
4908 SceneObjectPart part = parts[i];
4909 if (part == rootpart)
4910 continue;
4911 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4912 }
4913 }
4914
4915 public void SendAttachmentScheduleUpdate(SceneObjectGroup sog)
4916 {
4917 if (IsChildAgent || IsInTransit)
4918 return;
4919
4920 SceneObjectPart[] origparts = sog.Parts;
4921 SceneObjectPart[] parts = new SceneObjectPart[origparts.Length];
4922 PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length];
4923
4924 SceneObjectPart rootpart = sog.RootPart;
4925 UpdateRequired rootreq = sog.RootPart.UpdateFlag;
4926
4927 int j = 0;
4928 bool allterse = true;
4929 for (int i = 0; i < origparts.Length; i++)
4930 {
4931 if (origparts[i] != rootpart)
4932 {
4933 switch (origparts[i].UpdateFlag)
4934 {
4935 case UpdateRequired.NONE:
4936 break;
4937
4938 case UpdateRequired.TERSE:
4939 flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4940 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4941 parts[j] = origparts[i];
4942 j++;
4943 break;
4944
4945 case UpdateRequired.FULL:
4946 flags[j] = PrimUpdateFlags.FullUpdate;
4947 allterse = false;
4948 parts[j] = origparts[i];
4949 j++;
4950 break;
4951 }
4952 }
4953 origparts[i].UpdateFlag = 0;
4954 }
4955
4956 if (j == 0 && rootreq == UpdateRequired.NONE)
4957 return;
4958
4959 PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate;
4960
4961 if (rootreq != UpdateRequired.FULL && allterse)
4962 {
4963 rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4964 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4965 }
4966
4967 int nparts = j;
4968
4969 ControllingClient.SendEntityUpdate(rootpart, rootflag);
4970
4971 for (int i = 0; i < nparts; i++)
4972 {
4973 ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4974 }
4975
4976 if (sog.HasPrivateAttachmentPoint)
4977 return;
4978
4979 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4980 foreach (ScenePresence p in allPresences)
4981 {
4982 if (p == this)
4983 continue;
4984
4985 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4986 continue;
4987
4988 p.ControllingClient.SendEntityUpdate(rootpart, rootflag);
4989
4990 for (int i = 0; i < nparts; i++)
4991 {
4992 p.ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4993 }
4994 }
4995 }
4996
4997 public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag)
4998 {
4999 if (IsChildAgent || IsInTransit)
5000 return;
5001
5002 PrimUpdateFlags flag;
5003 switch (UpdateFlag)
5004 {
5005 case UpdateRequired.TERSE:
5006 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5007 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5008 break;
5009
5010 case UpdateRequired.FULL:
5011 flag = PrimUpdateFlags.FullUpdate;
5012 break;
5013
5014 default:
5015 return;
5016 }
5017
5018 SceneObjectPart[] parts = sog.Parts;
5019 SceneObjectPart rootpart = sog.RootPart;
5020
5021// rootpart.UpdateFlag = 0;
5022
5023 ControllingClient.SendEntityUpdate(rootpart, flag);
5024
5025 for (int i = 0; i < parts.Length; i++)
5026 {
5027 SceneObjectPart part = parts[i];
5028 if (part == rootpart)
5029 continue;
5030 ControllingClient.SendEntityUpdate(part, flag);
5031// part.UpdateFlag = 0;
5032 }
5033
5034 if (sog.HasPrivateAttachmentPoint)
5035 return;
5036
5037
5038 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5039 foreach (ScenePresence p in allPresences)
5040 {
5041 if (p == this)
5042 continue;
5043
5044 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5045 continue;
5046
5047 p.ControllingClient.SendEntityUpdate(rootpart, flag);
5048
5049 for (int i = 0; i < parts.Length; i++)
5050 {
5051 SceneObjectPart part = parts[i];
5052 if (part == rootpart)
5053 continue;
5054 p.ControllingClient.SendEntityUpdate(part, flag);
5055 }
5056 }
5057 }
5058
5059 public void SendAttachmentScheduleUpdate(SceneObjectPart part)
5060 {
5061 if (IsChildAgent || IsInTransit)
5062 return;
5063
5064
5065 PrimUpdateFlags flag;
5066 switch (part.UpdateFlag)
5067 {
5068 case UpdateRequired.TERSE:
5069 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5070 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5071 break;
5072
5073 case UpdateRequired.FULL:
5074 flag = PrimUpdateFlags.FullUpdate;
5075 break;
5076
5077 default:
5078 return;
5079 }
5080
5081 part.UpdateFlag = 0;
5082
5083 ControllingClient.SendEntityUpdate(part, flag);
5084
5085 if (part.ParentGroup.HasPrivateAttachmentPoint)
5086 return;
5087
5088 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5089 foreach (ScenePresence p in allPresences)
5090 {
5091 if (p == this)
5092 continue;
5093
5094 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5095 continue;
5096
5097 p.ControllingClient.SendEntityUpdate(part, flag);
5098 }
5099 }
5100
5101
5102 public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag)
5103 {
5104 if (IsChildAgent || IsInTransit)
5105 return;
5106
5107 PrimUpdateFlags flag;
5108 switch (UpdateFlag)
5109 {
5110 case UpdateRequired.TERSE:
5111 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5112 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5113 break;
5114
5115 case UpdateRequired.FULL:
5116 flag = PrimUpdateFlags.FullUpdate;
5117 break;
5118
5119 default:
5120 return;
5121 }
5122
5123// part.UpdateFlag = 0;
5124
5125 ControllingClient.SendEntityUpdate(part, flag);
5126
5127 if (part.ParentGroup.HasPrivateAttachmentPoint)
5128 return;
5129
5130 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5131 foreach (ScenePresence p in allPresences)
5132 {
5133 if (p == this)
5134 continue;
5135 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5136 continue;
5137
5138 p.ControllingClient.SendEntityUpdate(part, flag);
5139 }
5140 }
5141
4477 /// <summary> 5142 /// <summary>
4478 /// Send a script event to this scene presence's attachments 5143 /// Send a script event to this scene presence's attachments
4479 /// </summary> 5144 /// </summary>
@@ -4592,7 +5257,16 @@ namespace OpenSim.Region.Framework.Scenes
4592 ControllingClient.SendTakeControls(int.MaxValue, false, false); 5257 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4593 } 5258 }
4594 5259
4595 private void UnRegisterSeatControls(UUID obj) 5260 public void ClearControls()
5261 {
5262 IgnoredControls = ScriptControlled.CONTROL_ZERO;
5263 lock (scriptedcontrols)
5264 {
5265 scriptedcontrols.Clear();
5266 }
5267 }
5268
5269 public void UnRegisterSeatControls(UUID obj)
4596 { 5270 {
4597 List<UUID> takers = new List<UUID>(); 5271 List<UUID> takers = new List<UUID>();
4598 5272
@@ -4833,11 +5507,8 @@ namespace OpenSim.Region.Framework.Scenes
4833 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); 5507 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
4834 if (spawnPoints.Length == 0) 5508 if (spawnPoints.Length == 0)
4835 { 5509 {
4836 if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) 5510 pos.X = 128.0f;
4837 { 5511 pos.Y = 128.0f;
4838 pos.X = 128.0f;
4839 pos.Y = 128.0f;
4840 }
4841 return; 5512 return;
4842 } 5513 }
4843 5514
@@ -4982,8 +5653,8 @@ namespace OpenSim.Region.Framework.Scenes
4982 pos = land.LandData.UserLocation; 5653 pos = land.LandData.UserLocation;
4983 } 5654 }
4984 } 5655 }
4985 5656// this is now done in completeMovement for all cases and not just this
4986 land.SendLandUpdateToClient(ControllingClient); 5657// land.SendLandUpdateToClient(ControllingClient);
4987 } 5658 }
4988 } 5659 }
4989 5660
@@ -4998,6 +5669,7 @@ namespace OpenSim.Region.Framework.Scenes
4998 detobj.velVector = obj.Velocity; 5669 detobj.velVector = obj.Velocity;
4999 detobj.colliderType = 0; 5670 detobj.colliderType = 0;
5000 detobj.groupUUID = obj.GroupID; 5671 detobj.groupUUID = obj.GroupID;
5672 detobj.linkNumber = 0;
5001 5673
5002 return detobj; 5674 return detobj;
5003 } 5675 }
@@ -5013,6 +5685,7 @@ namespace OpenSim.Region.Framework.Scenes
5013 detobj.velVector = av.Velocity; 5685 detobj.velVector = av.Velocity;
5014 detobj.colliderType = 0; 5686 detobj.colliderType = 0;
5015 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 5687 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
5688 detobj.linkNumber = 0;
5016 5689
5017 return detobj; 5690 return detobj;
5018 } 5691 }
@@ -5028,7 +5701,7 @@ namespace OpenSim.Region.Framework.Scenes
5028 detobj.velVector = Vector3.Zero; 5701 detobj.velVector = Vector3.Zero;
5029 detobj.colliderType = 0; 5702 detobj.colliderType = 0;
5030 detobj.groupUUID = UUID.Zero; 5703 detobj.groupUUID = UUID.Zero;
5031 5704 detobj.linkNumber = 0;
5032 return detobj; 5705 return detobj;
5033 } 5706 }
5034 5707
@@ -5095,6 +5768,95 @@ namespace OpenSim.Region.Framework.Scenes
5095 } 5768 }
5096 } 5769 }
5097 5770
5771 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
5772 {
5773 try
5774 {
5775 List<uint> thisHitColliders = new List<uint>();
5776 List<uint> endedColliders = new List<uint>();
5777 List<uint> startedColliders = new List<uint>();
5778 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
5779 CollisionForSoundInfo soundinfo;
5780 ContactPoint curcontact;
5781
5782 if (coldata.Count == 0)
5783 {
5784 if (m_lastColliders.Count == 0)
5785 return; // nothing to do
5786
5787 foreach (uint localID in m_lastColliders)
5788 {
5789 endedColliders.Add(localID);
5790 }
5791 m_lastColliders.Clear();
5792 }
5793
5794 else
5795 {
5796 bool candoparcelSound = ParcelAllowThisAvatarSounds;
5797
5798 foreach (uint id in coldata.Keys)
5799 {
5800 thisHitColliders.Add(id);
5801 if (!m_lastColliders.Contains(id))
5802 {
5803 startedColliders.Add(id);
5804 curcontact = coldata[id];
5805 if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2)
5806 {
5807 soundinfo = new CollisionForSoundInfo();
5808 soundinfo.colliderID = id;
5809 soundinfo.position = curcontact.Position;
5810 soundinfo.relativeVel = curcontact.RelativeSpeed;
5811 soundinfolist.Add(soundinfo);
5812 }
5813 }
5814 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
5815 }
5816
5817 // calculate things that ended colliding
5818 foreach (uint localID in m_lastColliders)
5819 {
5820 if (!thisHitColliders.Contains(localID))
5821 {
5822 endedColliders.Add(localID);
5823 }
5824 }
5825 //add the items that started colliding this time to the last colliders list.
5826 foreach (uint localID in startedColliders)
5827 {
5828 m_lastColliders.Add(localID);
5829 }
5830 // remove things that ended colliding from the last colliders list
5831 foreach (uint localID in endedColliders)
5832 {
5833 m_lastColliders.Remove(localID);
5834 }
5835
5836 if (soundinfolist.Count > 0)
5837 CollisionSounds.AvatarCollisionSound(this, soundinfolist);
5838 }
5839
5840 foreach (SceneObjectGroup att in GetAttachments())
5841 {
5842 SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart);
5843 SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding);
5844 SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd);
5845
5846 if (startedColliders.Contains(0))
5847 SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart);
5848 if (m_lastColliders.Contains(0))
5849 SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding);
5850 if (endedColliders.Contains(0))
5851 SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd);
5852 }
5853 }
5854 finally
5855 {
5856 m_collisionEventFlag = false;
5857 }
5858 }
5859
5098 private void TeleportFlagsDebug() { 5860 private void TeleportFlagsDebug() {
5099 5861
5100 // Some temporary debugging help to show all the TeleportFlags we have... 5862 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -5119,5 +5881,282 @@ namespace OpenSim.Region.Framework.Scenes
5119 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 5881 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
5120 5882
5121 } 5883 }
5884
5885 private void parcelGodCheck(UUID currentParcelID, bool isGod)
5886 {
5887 List<ScenePresence> allpresences = m_scene.GetScenePresences();
5888
5889 foreach (ScenePresence p in allpresences)
5890 {
5891 if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5892 continue;
5893
5894 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5895 {
5896 if (isGod)
5897 p.SendViewTo(this);
5898 else
5899 p.SendKillTo(this);
5900 }
5901 }
5902 }
5903
5904 private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
5905 bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
5906 {
5907 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5908 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5909 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5910 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5911 List<ScenePresence> allpresences = null;
5912
5913 if (IsInTransit || IsChildAgent)
5914 return;
5915
5916 if (check)
5917 {
5918 // check is relative to current parcel only
5919 if (currentParcelUUID == null || oldhide == currentParcelHide)
5920 return;
5921
5922 allpresences = m_scene.GetScenePresences();
5923
5924 if (oldhide)
5925 { // where private
5926 foreach (ScenePresence p in allpresences)
5927 {
5928 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5929 continue;
5930
5931 // those on not on parcel see me
5932 if (currentParcelID != p.currentParcelUUID)
5933 {
5934 viewsToSendto.Add(p); // they see me
5935 }
5936 }
5937 } // where private end
5938
5939 else
5940 { // where public
5941 foreach (ScenePresence p in allpresences)
5942 {
5943 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5944 continue;
5945
5946 // those not on parcel dont see me
5947 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5948 {
5949 killsToSendto.Add(p); // they dont see me
5950 }
5951 }
5952 } // where public end
5953
5954 allpresences.Clear();
5955 }
5956 else
5957 {
5958 if (currentParcelHide)
5959 {
5960 // now on a private parcel
5961 allpresences = m_scene.GetScenePresences();
5962
5963 if (previusParcelHide && previusParcelID != UUID.Zero)
5964 {
5965 foreach (ScenePresence p in allpresences)
5966 {
5967 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5968 continue;
5969
5970 // only those on previus parcel need receive kills
5971 if (previusParcelID == p.currentParcelUUID)
5972 {
5973 if(p.GodLevel < 200)
5974 killsToSendto.Add(p); // they dont see me
5975 if(GodLevel < 200)
5976 killsToSendme.Add(p); // i dont see them
5977 }
5978 // only those on new parcel need see
5979 if (currentParcelID == p.currentParcelUUID)
5980 {
5981 viewsToSendto.Add(p); // they see me
5982 viewsToSendme.Add(p); // i see them
5983 }
5984 }
5985 }
5986 else
5987 {
5988 //was on a public area
5989 allpresences = m_scene.GetScenePresences();
5990
5991 foreach (ScenePresence p in allpresences)
5992 {
5993 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5994 continue;
5995
5996 // those not on new parcel dont see me
5997 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5998 {
5999 killsToSendto.Add(p); // they dont see me
6000 }
6001 else
6002 {
6003 viewsToSendme.Add(p); // i see those on it
6004 }
6005 }
6006 }
6007 allpresences.Clear();
6008 } // now on a private parcel end
6009
6010 else
6011 {
6012 // now on public parcel
6013 if (previusParcelHide && previusParcelID != UUID.Zero)
6014 {
6015 // was on private area
6016 allpresences = m_scene.GetScenePresences();
6017
6018 foreach (ScenePresence p in allpresences)
6019 {
6020 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6021 continue;
6022 // only those old parcel need kills
6023 if (previusParcelID == p.currentParcelUUID && GodLevel < 200)
6024 {
6025 killsToSendme.Add(p); // i dont see them
6026 }
6027 else
6028 {
6029 viewsToSendto.Add(p); // they see me
6030 }
6031 }
6032 }
6033 else
6034 return; // was on a public area also
6035 } // now on public parcel end
6036 }
6037
6038 // send the things
6039
6040 if (killsToSendto.Count > 0)
6041 {
6042 foreach (ScenePresence p in killsToSendto)
6043 {
6044 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
6045 SendKillTo(p);
6046 }
6047 }
6048
6049 if (killsToSendme.Count > 0)
6050 {
6051 foreach (ScenePresence p in killsToSendme)
6052 {
6053 m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname);
6054 p.SendKillTo(this);
6055 }
6056 }
6057
6058 if (viewsToSendto.Count > 0)
6059 {
6060 foreach (ScenePresence p in viewsToSendto)
6061 {
6062 SendViewTo(p);
6063 }
6064 }
6065
6066 if (viewsToSendme.Count > 0 )
6067 {
6068 foreach (ScenePresence p in viewsToSendme)
6069 {
6070 if (p.IsChildAgent)
6071 continue;
6072// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
6073 p.SendViewTo(this);
6074 }
6075 }
6076 }
6077
6078 public void HasMovedAway(bool nearRegion)
6079 {
6080
6081 if (nearRegion)
6082 {
6083 if (Scene.AttachmentsModule != null)
6084 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6085
6086 if (!ParcelHideThisAvatar || GodLevel >= 200)
6087 return;
6088
6089 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6090 foreach (ScenePresence p in allpresences)
6091 {
6092 if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive)
6093 continue;
6094
6095 if (p.currentParcelUUID == m_currentParcelUUID)
6096 {
6097 p.SendKillTo(this);
6098 }
6099 }
6100 }
6101 else
6102 {
6103 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6104 foreach (ScenePresence p in allpresences)
6105 {
6106 if (p == this)
6107 continue;
6108 SendKillTo(p);
6109 if (!p.IsChildAgent)
6110 p.SendKillTo(this);
6111 }
6112
6113 if (Scene.AttachmentsModule != null)
6114 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6115 }
6116 }
6117
6118
6119// kill with attachs root kills
6120 public void SendKillTo(ScenePresence p)
6121 {
6122 List<uint> ids = new List<uint>(m_attachments.Count + 1);
6123 foreach (SceneObjectGroup sog in m_attachments)
6124 {
6125 ids.Add(sog.RootPart.LocalId);
6126 }
6127
6128 ids.Add(LocalId);
6129 p.ControllingClient.SendKillObject(ids);
6130 }
6131
6132/*
6133// kill with hack
6134 public void SendKillTo(ScenePresence p)
6135 {
6136 foreach (SceneObjectGroup sog in m_attachments)
6137 p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1);
6138 p.ControllingClient.SendKillObject(new List<uint> { LocalId });
6139 }
6140*/
6141 public void SendViewTo(ScenePresence p)
6142 {
6143 SendAvatarDataToAgentNF(p);
6144 SendAppearanceToAgent(p);
6145 if (Animator != null)
6146 Animator.SendAnimPackToClient(p.ControllingClient);
6147 SendAttachmentsToAgentNF(p);
6148 }
6149
6150 public void SetAnimationOverride(string animState, UUID animID)
6151 {
6152 Overrides.SetOverride(animState, animID);
6153// Animator.SendAnimPack();
6154 Animator.ForceUpdateMovementAnimations();
6155 }
6156
6157 public UUID GetAnimationOverride(string animState)
6158 {
6159 return Overrides.GetOverriddenAnimation(animState);
6160 }
5122 } 6161 }
5123} 6162}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 4caa9cb..7d3a168 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -278,7 +278,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
278 // Script state may, or may not, exist. Not having any, is NOT 278 // Script state may, or may not, exist. Not having any, is NOT
279 // ever a problem. 279 // ever a problem.
280 sceneObject.LoadScriptState(doc); 280 sceneObject.LoadScriptState(doc);
281 281
282 return sceneObject; 282 return sceneObject;
283 } 283 }
284 catch (Exception e) 284 catch (Exception e)
@@ -307,14 +307,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
307 } 307 }
308 } 308 }
309 309
310
311 /// <summary> 310 /// <summary>
312 /// Modifies a SceneObjectGroup. 311 /// Modifies a SceneObjectGroup.
313 /// </summary> 312 /// </summary>
314 /// <param name="sog">The object</param> 313 /// <param name="sog">The object</param>
315 /// <returns>Whether the object was actually modified</returns> 314 /// <returns>Whether the object was actually modified</returns>
316 public delegate bool SceneObjectModifier(SceneObjectGroup sog); 315 public delegate bool SceneObjectModifier(SceneObjectGroup sog);
317 316
318 /// <summary> 317 /// <summary>
319 /// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing. 318 /// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing.
320 /// </summary> 319 /// </summary>
@@ -328,7 +327,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
328 CoalescedSceneObjects coa = null; 327 CoalescedSceneObjects coa = null;
329 328
330 string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data)); 329 string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data));
331
332 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) 330 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa))
333 { 331 {
334 // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); 332 // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count);
@@ -374,7 +372,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
374 return data; 372 return data;
375 } 373 }
376 374
377
378 #region manual serialization 375 #region manual serialization
379 376
380 private static Dictionary<string, Action<SceneObjectPart, XmlReader>> m_SOPXmlProcessors 377 private static Dictionary<string, Action<SceneObjectPart, XmlReader>> m_SOPXmlProcessors
@@ -450,11 +447,28 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
450 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 447 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
451 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 448 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
452 449
450 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
451 m_SOPXmlProcessors.Add("Force", ProcessForce);
452 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
453 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
454
455
456 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
457
458 m_SOPXmlProcessors.Add("RotationAxisLocks", ProcessRotationAxisLocks);
453 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType); 459 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType);
454 m_SOPXmlProcessors.Add("Density", ProcessDensity); 460 m_SOPXmlProcessors.Add("Density", ProcessDensity);
455 m_SOPXmlProcessors.Add("Friction", ProcessFriction); 461 m_SOPXmlProcessors.Add("Friction", ProcessFriction);
456 m_SOPXmlProcessors.Add("Bounce", ProcessBounce); 462 m_SOPXmlProcessors.Add("Bounce", ProcessBounce);
457 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier); 463 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier);
464 m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset);
465 m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset);
466
467 m_SOPXmlProcessors.Add("SoundID", ProcessSoundID);
468 m_SOPXmlProcessors.Add("SoundGain", ProcessSoundGain);
469 m_SOPXmlProcessors.Add("SoundFlags", ProcessSoundFlags);
470 m_SOPXmlProcessors.Add("SoundRadius", ProcessSoundRadius);
471 m_SOPXmlProcessors.Add("SoundQueueing", ProcessSoundQueueing);
458 472
459 #endregion 473 #endregion
460 474
@@ -483,7 +497,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
483 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask); 497 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask);
484 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType); 498 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType);
485 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged); 499 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged);
486 500
487 #endregion 501 #endregion
488 502
489 #region ShapeXmlProcessors initialization 503 #region ShapeXmlProcessors initialization
@@ -684,6 +698,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
684 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 698 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
685 } 699 }
686 700
701 private static void ProcessRotationAxisLocks(SceneObjectPart obj, XmlReader reader)
702 {
703 obj.RotationAxisLocks = (byte)reader.ReadElementContentAsInt("RotationAxisLocks", String.Empty);
704 }
705
687 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlReader reader) 706 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlReader reader)
688 { 707 {
689 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty); 708 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty);
@@ -709,6 +728,58 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
709 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty); 728 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty);
710 } 729 }
711 730
731 private static void ProcessCameraEyeOffset(SceneObjectPart obj, XmlReader reader)
732 {
733 obj.SetCameraEyeOffset(Util.ReadVector(reader, "CameraEyeOffset"));
734 }
735
736 private static void ProcessCameraAtOffset(SceneObjectPart obj, XmlReader reader)
737 {
738 obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset"));
739 }
740
741 private static void ProcessSoundID(SceneObjectPart obj, XmlReader reader)
742 {
743 obj.Sound = Util.ReadUUID(reader, "SoundID");
744 }
745
746 private static void ProcessSoundGain(SceneObjectPart obj, XmlReader reader)
747 {
748 obj.SoundGain = reader.ReadElementContentAsDouble("SoundGain", String.Empty);
749 }
750
751 private static void ProcessSoundFlags(SceneObjectPart obj, XmlReader reader)
752 {
753 obj.SoundFlags = (byte)reader.ReadElementContentAsInt("SoundFlags", String.Empty);
754 }
755
756 private static void ProcessSoundRadius(SceneObjectPart obj, XmlReader reader)
757 {
758 obj.SoundRadius = reader.ReadElementContentAsDouble("SoundRadius", String.Empty);
759 }
760
761 private static void ProcessSoundQueueing(SceneObjectPart obj, XmlReader reader)
762 {
763 obj.SoundQueueing = Util.ReadBoolean(reader);
764 }
765
766 private static void ProcessVehicle(SceneObjectPart obj, XmlReader reader)
767 {
768 SOPVehicle vehicle = SOPVehicle.FromXml2(reader);
769
770 if (vehicle == null)
771 {
772 obj.VehicleParams = null;
773 m_log.DebugFormat(
774 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
775 obj.Name, obj.UUID);
776 }
777 else
778 {
779 obj.VehicleParams = vehicle;
780 }
781 }
782
712 private static void ProcessShape(SceneObjectPart obj, XmlReader reader) 783 private static void ProcessShape(SceneObjectPart obj, XmlReader reader)
713 { 784 {
714 List<string> errorNodeNames; 785 List<string> errorNodeNames;
@@ -883,6 +954,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
883 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 954 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
884 } 955 }
885 956
957 private static void ProcessBuoyancy(SceneObjectPart obj, XmlReader reader)
958 {
959 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
960 }
961
962 private static void ProcessForce(SceneObjectPart obj, XmlReader reader)
963 {
964 obj.Force = Util.ReadVector(reader, "Force");
965 }
966 private static void ProcessTorque(SceneObjectPart obj, XmlReader reader)
967 {
968 obj.Torque = Util.ReadVector(reader, "Torque");
969 }
970
971 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlReader reader)
972 {
973 obj.VolumeDetectActive = Util.ReadBoolean(reader);
974 }
975
886 #endregion 976 #endregion
887 977
888 #region TaskInventoryXmlProcessors 978 #region TaskInventoryXmlProcessors
@@ -1271,12 +1361,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1271 1361
1272 if (sog.RootPart.KeyframeMotion != null) 1362 if (sog.RootPart.KeyframeMotion != null)
1273 { 1363 {
1274 Byte[] data = sog.RootPart.KeyframeMotion.Serialize(); 1364 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1275 1365
1276 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); 1366 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1277 writer.WriteBase64(data, 0, data.Length); 1367 writer.WriteBase64(data, 0, data.Length);
1278 writer.WriteEndElement(); 1368 writer.WriteEndElement();
1279 } 1369 }
1370
1280 1371
1281 writer.WriteEndElement(); 1372 writer.WriteEndElement();
1282 } 1373 }
@@ -1388,8 +1479,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1388 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1479 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1389 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1480 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1390 1481
1391 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType()) 1482 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1392 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); 1483
1484 WriteVector(writer, "Force", sop.Force);
1485 WriteVector(writer, "Torque", sop.Torque);
1486
1487 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1488
1489 if (sop.VehicleParams != null)
1490 sop.VehicleParams.ToXml2(writer);
1491
1492 if(sop.RotationAxisLocks != 0)
1493 writer.WriteElementString("RotationAxisLocks", sop.RotationAxisLocks.ToString().ToLower());
1494 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1393 if (sop.Density != 1000.0f) 1495 if (sop.Density != 1000.0f)
1394 writer.WriteElementString("Density", sop.Density.ToString().ToLower()); 1496 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1395 if (sop.Friction != 0.6f) 1497 if (sop.Friction != 0.6f)
@@ -1398,7 +1500,18 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1398 writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower()); 1500 writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower());
1399 if (sop.GravityModifier != 1.0f) 1501 if (sop.GravityModifier != 1.0f)
1400 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower()); 1502 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
1503 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
1504 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
1401 1505
1506 // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
1507 {
1508 WriteUUID(writer, "SoundID", sop.Sound, options);
1509 writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower());
1510 writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower());
1511 writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower());
1512 }
1513 writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower());
1514
1402 writer.WriteEndElement(); 1515 writer.WriteEndElement();
1403 } 1516 }
1404 1517
@@ -1625,12 +1738,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1625 { 1738 {
1626 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1739 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1627 1740
1628 if (reader.IsEmptyElement)
1629 {
1630 reader.Read();
1631 return tinv;
1632 }
1633
1634 reader.ReadStartElement(name, String.Empty); 1741 reader.ReadStartElement(name, String.Empty);
1635 1742
1636 while (reader.Name == "TaskInventoryItem") 1743 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 3effee7..c8f525e 100755
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Timers; 30using System.Timers;
31using System.Threading;
31using OpenMetaverse.Packets; 32using OpenMetaverse.Packets;
32using OpenSim.Framework; 33using OpenSim.Framework;
33using OpenSim.Framework.Monitoring; 34using OpenSim.Framework.Monitoring;
@@ -62,8 +63,10 @@ namespace OpenSim.Region.Framework.Scenes
62 private YourStatsAreWrong handlerStatsIncorrect; 63 private YourStatsAreWrong handlerStatsIncorrect;
63 64
64 // Determines the size of the array that is used to collect StatBlocks 65 // Determines the size of the array that is used to collect StatBlocks
65 // for sending to the SimStats and SimExtraStatsCollector 66 // for sending viewer compatible stats must be conform with sb array filling below
66 private const int m_statisticArraySize = 28; 67 private const int m_statisticViewerArraySize = 38;
68 // size of LastReportedSimFPS with extra stats.
69 private const int m_statisticExtraArraySize = (int)(Stats.SimExtraCountEnd - Stats.SimExtraCountStart);
67 70
68 /// <summary> 71 /// <summary>
69 /// These are the IDs of stats sent in the StatsPacket to the viewer. 72 /// These are the IDs of stats sent in the StatsPacket to the viewer.
@@ -74,6 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
74 /// </remarks> 77 /// </remarks>
75 public enum Stats : uint 78 public enum Stats : uint
76 { 79 {
80// viewers defined IDs
77 TimeDilation = 0, 81 TimeDilation = 0,
78 SimFPS = 1, 82 SimFPS = 1,
79 PhysicsFPS = 2, 83 PhysicsFPS = 2,
@@ -90,7 +94,7 @@ namespace OpenSim.Region.Framework.Scenes
90 Agents = 13, 94 Agents = 13,
91 ChildAgents = 14, 95 ChildAgents = 14,
92 ActiveScripts = 15, 96 ActiveScripts = 15,
93 ScriptLinesPerSecond = 16, 97 LSLScriptLinesPerSecond = 16, // viewers don't like this anymore
94 InPacketsPerSecond = 17, 98 InPacketsPerSecond = 17,
95 OutPacketsPerSecond = 18, 99 OutPacketsPerSecond = 18,
96 PendingDownloads = 19, 100 PendingDownloads = 19,
@@ -109,11 +113,24 @@ namespace OpenSim.Region.Framework.Scenes
109 SimSpareMs = 32, 113 SimSpareMs = 32,
110 SimSleepMs = 33, 114 SimSleepMs = 33,
111 SimIoPumpTime = 34, 115 SimIoPumpTime = 34,
112 FrameDilation = 35, 116 SimPCTSscriptsRun = 35,
113 UsersLoggingIn = 36, 117 SimRegionIdle = 36, // dataserver only
114 TotalGeoPrim = 37, 118 SimRegionIdlePossible = 37, // dataserver only
115 TotalMesh = 38, 119 SimAIStepTimeMS = 38,
116 ThreadCount = 39 120 SimSkippedSillouet_PS = 39,
121 SimSkippedCharsPerC = 40,
122
123// extra stats IDs irrelevant, just far from viewer defined ones
124 SimExtraCountStart = 1000,
125
126 internalLSLScriptLinesPerSecond = 1000,
127 FrameDilation2 = 1001,
128 UsersLoggingIn = 1002,
129 TotalGeoPrim = 1003,
130 TotalMesh = 1004,
131 ThreadCount = 1005,
132
133 SimExtraCountEnd = 1006
117 } 134 }
118 135
119 /// <summary> 136 /// <summary>
@@ -158,19 +175,14 @@ namespace OpenSim.Region.Framework.Scenes
158 175
159 // Sending a stats update every 3 seconds- 176 // Sending a stats update every 3 seconds-
160 private int m_statsUpdatesEveryMS = 3000; 177 private int m_statsUpdatesEveryMS = 3000;
161 private float m_statsUpdateFactor; 178 private double m_lastUpdateTS;
179 private double m_prevFrameStatsTS;
180 private double m_FrameStatsTS;
162 private float m_timeDilation; 181 private float m_timeDilation;
163 private int m_fps; 182 private int m_fps;
164 183
165 /// <summary> 184 private object m_statsLock = new object();
166 /// Number of the last frame on which we processed a stats udpate. 185 private object m_statsFrameLock = new object();
167 /// </summary>
168 private uint m_lastUpdateFrame;
169
170 /// <summary>
171 /// Our nominal fps target, as expected in fps stats when a sim is running normally.
172 /// </summary>
173 private float m_nominalReportedFps = 55;
174 186
175 /// <summary> 187 /// <summary>
176 /// Parameter to adjust reported scene fps 188 /// Parameter to adjust reported scene fps
@@ -186,10 +198,10 @@ namespace OpenSim.Region.Framework.Scenes
186 /// corresponding, with default heartbeat rate, to a value of 5. 198 /// corresponding, with default heartbeat rate, to a value of 5.
187 /// </remarks> 199 /// </remarks>
188 private float m_statisticsFPSfactor = 5.0f; 200 private float m_statisticsFPSfactor = 5.0f;
189 201 private float m_targetFrameTime = 0.1f;
190 // saved last reported value so there is something available for llGetRegionFPS 202 // saved last reported value so there is something available for llGetRegionFPS
191 private float lastReportedSimFPS; 203 private float lastReportedSimFPS;
192 private float[] lastReportedSimStats = new float[m_statisticArraySize]; 204 private float[] lastReportedSimStats = new float[m_statisticExtraArraySize + m_statisticViewerArraySize];
193 private float m_pfps; 205 private float m_pfps;
194 206
195 /// <summary> 207 /// <summary>
@@ -202,14 +214,15 @@ namespace OpenSim.Region.Framework.Scenes
202 /// </summary> 214 /// </summary>
203 private int m_objectUpdates; 215 private int m_objectUpdates;
204 216
205 private int m_frameMS; 217 private float m_frameMS;
206 private int m_spareMS; 218
207 private int m_netMS; 219 private float m_netMS;
208 private int m_agentMS; 220 private float m_agentMS;
209 private int m_physicsMS; 221 private float m_physicsMS;
210 private int m_imageMS; 222 private float m_imageMS;
211 private int m_otherMS; 223 private float m_otherMS;
212 private int m_scriptMS; 224 private float m_sleeptimeMS;
225 private float m_scriptTimeMS;
213 226
214 private int m_rootAgents; 227 private int m_rootAgents;
215 private int m_childAgents; 228 private int m_childAgents;
@@ -224,31 +237,11 @@ namespace OpenSim.Region.Framework.Scenes
224 private int m_pendingUploads = 0; // FIXME: Not currently filled in 237 private int m_pendingUploads = 0; // FIXME: Not currently filled in
225 private int m_activeScripts; 238 private int m_activeScripts;
226 private int m_scriptLinesPerSecond; 239 private int m_scriptLinesPerSecond;
240 private int m_scriptEventsPerSecond;
227 241
228 private int m_objectCapacity = 45000; 242 private int m_objectCapacity = 45000;
229 243
230 // This is the number of frames that will be stored and then averaged for 244 // The current number of users attempting to login to the region
231 // the Total, Simulation, Physics, and Network Frame Time; It is set to
232 // 10 by default but can be changed by the OpenSim.ini configuration file
233 // NumberOfFrames parameter
234 private int m_numberFramesStored;
235
236 // The arrays that will hold the time it took to run the past N frames,
237 // where N is the num_frames_to_average given by the configuration file
238 private double[] m_totalFrameTimeMilliseconds;
239 private double[] m_simulationFrameTimeMilliseconds;
240 private double[] m_physicsFrameTimeMilliseconds;
241 private double[] m_networkFrameTimeMilliseconds;
242
243 // The location of the next time in milliseconds that will be
244 // (over)written when the next frame completes
245 private int m_nextLocation = 0;
246
247 // The correct number of frames that have completed since the last stats
248 // update for physics
249 private int m_numberPhysicsFrames;
250
251 // The current number of users attempting to login to the region
252 private int m_usersLoggingIn; 245 private int m_usersLoggingIn;
253 246
254 // The last reported value of threads from the SmartThreadPool inside of 247 // The last reported value of threads from the SmartThreadPool inside of
@@ -259,51 +252,39 @@ namespace OpenSim.Region.Framework.Scenes
259 252
260 private RegionInfo ReportingRegion; 253 private RegionInfo ReportingRegion;
261 254
262 private Timer m_report = new Timer(); 255 private System.Timers.Timer m_report = new System.Timers.Timer();
263 256
264 private IEstateModule estateModule; 257 private IEstateModule estateModule;
265 258
266 public SimStatsReporter(Scene scene) 259 public SimStatsReporter(Scene scene)
267 : this(scene, Scene.m_defaultNumberFramesStored)
268 {
269 }
270
271 public SimStatsReporter(Scene scene, int numberOfFrames)
272 { 260 {
273 // Store the number of frames from the OpenSim.ini configuration file
274 m_numberFramesStored = numberOfFrames;
275
276 // Initialize the different frame time arrays to the correct sizes
277 m_totalFrameTimeMilliseconds = new double[m_numberFramesStored];
278 m_simulationFrameTimeMilliseconds = new double[m_numberFramesStored];
279 m_physicsFrameTimeMilliseconds = new double[m_numberFramesStored];
280 m_networkFrameTimeMilliseconds = new double[m_numberFramesStored];
281
282 // Initialize the current number of users logging into the region
283 m_usersLoggingIn = 0;
284
285 m_scene = scene; 261 m_scene = scene;
286 262
287 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000);
288 ReportingRegion = scene.RegionInfo; 263 ReportingRegion = scene.RegionInfo;
289 264
290 if(scene.Normalized55FPS) 265 if(scene.Normalized55FPS)
291 m_statisticsFPSfactor = 55.0f * m_scene.MinFrameTicks / 1000.0f; 266 m_statisticsFPSfactor = 55.0f * m_scene.FrameTime;
292 else 267 else
293 m_statisticsFPSfactor = 1.0f; 268 m_statisticsFPSfactor = 1.0f;
294 269
270 m_targetFrameTime = 1000.0f * m_scene.FrameTime / m_statisticsFPSfactor;
271
295 m_objectCapacity = scene.RegionInfo.ObjectCapacity; 272 m_objectCapacity = scene.RegionInfo.ObjectCapacity;
296 m_report.AutoReset = true; 273 m_report.AutoReset = true;
297 m_report.Interval = m_statsUpdatesEveryMS; 274 m_report.Interval = m_statsUpdatesEveryMS;
298 m_report.Elapsed += TriggerStatsHeartbeat; 275 m_report.Elapsed += TriggerStatsHeartbeat;
299 m_report.Enabled = true; 276 m_report.Enabled = true;
300 277
278 m_lastUpdateTS = Util.GetTimeStampMS();
279 m_FrameStatsTS = m_lastUpdateTS;
280 m_prevFrameStatsTS = m_lastUpdateTS;
281
301 if (StatsManager.SimExtraStats != null) 282 if (StatsManager.SimExtraStats != null)
302 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; 283 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
303 284
304 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit 285 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
305 /// longer than ideal (which in itself is a concern). 286 /// longer than ideal (which in itself is a concern).
306 SlowFramesStatReportThreshold = (int)Math.Ceiling(scene.MinFrameTicks * 1.2); 287 SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.FrameTime * 1000 * 1.2);
307 288
308 SlowFramesStat 289 SlowFramesStat
309 = new Stat( 290 = new Stat(
@@ -318,7 +299,6 @@ namespace OpenSim.Region.Framework.Scenes
318 StatVerbosity.Info); 299 StatVerbosity.Info);
319 300
320 StatsManager.RegisterStat(SlowFramesStat); 301 StatsManager.RegisterStat(SlowFramesStat);
321
322 } 302 }
323 303
324 304
@@ -335,7 +315,6 @@ namespace OpenSim.Region.Framework.Scenes
335 public void SetUpdateMS(int ms) 315 public void SetUpdateMS(int ms)
336 { 316 {
337 m_statsUpdatesEveryMS = ms; 317 m_statsUpdatesEveryMS = ms;
338 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000);
339 m_report.Interval = m_statsUpdatesEveryMS; 318 m_report.Interval = m_statsUpdatesEveryMS;
340 } 319 }
341 320
@@ -355,29 +334,20 @@ namespace OpenSim.Region.Framework.Scenes
355 334
356 private void statsHeartBeat(object sender, EventArgs e) 335 private void statsHeartBeat(object sender, EventArgs e)
357 { 336 {
358 double totalSumFrameTime; 337 if (!m_scene.Active)
359 double simulationSumFrameTime;
360 double physicsSumFrameTime;
361 double networkSumFrameTime;
362 float frameDilation;
363 int currentFrame;
364
365 if (!m_scene.Active)
366 return; 338 return;
367
368 // Create arrays to hold the statistics for this current scene,
369 // these will be passed to the SimExtraStatsCollector, they are also
370 // sent to the SimStats class
371 SimStatsPacket.StatBlock[] sb = new
372 SimStatsPacket.StatBlock[m_statisticArraySize];
373 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
374 339
375 // Know what's not thread safe in Mono... modifying timers. 340 // dont do it if if still been done
376 // m_log.Debug("Firing Stats Heart Beat"); 341
377 lock (m_report) 342 if(Monitor.TryEnter(m_statsLock))
378 { 343 {
344 // m_log.Debug("Firing Stats Heart Beat");
345
346 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[m_statisticViewerArraySize];
347 SimStatsPacket.StatBlock[] sbex = new SimStatsPacket.StatBlock[m_statisticExtraArraySize];
348 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
379 uint regionFlags = 0; 349 uint regionFlags = 0;
380 350
381 try 351 try
382 { 352 {
383 if (estateModule == null) 353 if (estateModule == null)
@@ -390,22 +360,93 @@ namespace OpenSim.Region.Framework.Scenes
390 } 360 }
391 361
392#region various statistic googly moogly 362#region various statistic googly moogly
363 double timeTmp = m_lastUpdateTS;
364 m_lastUpdateTS = Util.GetTimeStampMS();
365 float updateElapsed = (float)((m_lastUpdateTS - timeTmp)/1000.0);
366
367 // factor to consider updates integration time
368 float updateTimeFactor = 1.0f / updateElapsed;
369
370
371 // scene frame stats
372 float reportedFPS;
373 float physfps;
374 float timeDilation;
375 float agentMS;
376 float physicsMS;
377 float otherMS;
378 float sleeptime;
379 float scriptTimeMS;
380 float totalFrameTime;
381
382 float invFrameElapsed;
383
384 // get a copy under lock and reset
385 lock(m_statsFrameLock)
386 {
387 timeDilation = m_timeDilation;
388 reportedFPS = m_fps;
389 physfps = m_pfps;
390 agentMS = m_agentMS;
391 physicsMS = m_physicsMS;
392 otherMS = m_otherMS;
393 sleeptime = m_sleeptimeMS;
394 scriptTimeMS = m_scriptTimeMS;
395 totalFrameTime = m_frameMS;
396 // still not inv
397 invFrameElapsed = (float)((m_FrameStatsTS - m_prevFrameStatsTS) / 1000.0);
398
399 ResetFrameStats();
400 }
401
402 if (invFrameElapsed / updateElapsed < 0.8)
403 // scene is in trouble, its account of time is most likely wrong
404 // can even be in stall
405 invFrameElapsed = updateTimeFactor;
406 else
407 invFrameElapsed = 1.0f / invFrameElapsed;
408
409 float perframefactor;
410 if (reportedFPS <= 0)
411 {
412 reportedFPS = 0.0f;
413 physfps = 0.0f;
414 perframefactor = 1.0f;
415 timeDilation = 0.0f;
416 }
417 else
418 {
419 timeDilation /= reportedFPS;
420 reportedFPS *= m_statisticsFPSfactor;
421 perframefactor = 1.0f / (float)reportedFPS;
422 reportedFPS *= invFrameElapsed;
423 physfps *= invFrameElapsed * m_statisticsFPSfactor;
424 }
393 425
394 int reportedFPS = (int)(m_fps * m_statisticsFPSfactor); 426 // some engines track frame time with error related to the simulation step size
427 if(physfps > reportedFPS)
428 physfps = reportedFPS;
395 429
396 // save the reported value so there is something available for llGetRegionFPS 430 // save the reported value so there is something available for llGetRegionFPS
397 lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; 431 lastReportedSimFPS = reportedFPS;
398 432
399 // ORIGINAL code commented out until we have time to add our own 433 // scale frame stats
400 // statistics to the statistics window
401 //float physfps = ((m_pfps / 1000));
402 float physfps = m_numberPhysicsFrames * m_statisticsFPSfactor;
403 434
404 //if (physfps > 600) 435 totalFrameTime *= perframefactor;
405 //physfps = physfps - (physfps - 600); 436 sleeptime *= perframefactor;
437 otherMS *= perframefactor;
438 physicsMS *= perframefactor;
439 agentMS *= perframefactor;
440 scriptTimeMS *= perframefactor;
406 441
407 if (physfps < 0) 442 // estimate spare time
408 physfps = 0; 443 float sparetime;
444 sparetime = m_targetFrameTime - (physicsMS + agentMS + otherMS);
445
446 if (sparetime < 0)
447 sparetime = 0;
448 else if (sparetime > totalFrameTime)
449 sparetime = totalFrameTime;
409 450
410#endregion 451#endregion
411 452
@@ -416,79 +457,28 @@ namespace OpenSim.Region.Framework.Scenes
416 m_numMesh = m_scene.SceneGraph.GetTotalMeshObjectsCount(); 457 m_numMesh = m_scene.SceneGraph.GetTotalMeshObjectsCount();
417 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount(); 458 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount();
418 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount(); 459 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount();
460 m_scriptLinesPerSecond = m_scene.SceneGraph.GetScriptLPS();
419 461
420 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code 462 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code
421 // so that stat numbers are always consistent. 463 // so that stat numbers are always consistent.
422 CheckStatSanity(); 464 CheckStatSanity();
423 465
424 //Our time dilation is 0.91 when we're running a full speed, 466 for (int i = 0; i < m_statisticViewerArraySize; i++)
425 // therefore to make sure we get an appropriate range,
426 // we have to factor in our error. (0.10f * statsUpdateFactor)
427 // multiplies the fix for the error times the amount of times it'll occur a second
428 // / 10 divides the value by the number of times the sim heartbeat runs (10fps)
429 // Then we divide the whole amount by the amount of seconds pass in between stats updates.
430
431 // 'statsUpdateFactor' is how often stats packets are sent in seconds. Used below to change
432 // values to X-per-second values.
433
434 uint thisFrame = m_scene.Frame;
435 uint numFrames = thisFrame - m_lastUpdateFrame;
436 float framesUpdated = (float)numFrames * m_statisticsFPSfactor;
437 m_lastUpdateFrame = thisFrame;
438
439 // Avoid div-by-zero if somehow we've not updated any frames.
440 if (framesUpdated == 0)
441 framesUpdated = 1;
442
443 for (int i = 0; i < m_statisticArraySize; i++)
444 { 467 {
445 sb[i] = new SimStatsPacket.StatBlock(); 468 sb[i] = new SimStatsPacket.StatBlock();
446 } 469 }
447 470
448 // Resetting the sums of the frame times to prevent any errors
449 // in calculating the moving average for frame time
450 totalSumFrameTime = 0;
451 simulationSumFrameTime = 0;
452 physicsSumFrameTime = 0;
453 networkSumFrameTime = 0;
454
455 // Loop through all the frames that were stored for the current
456 // heartbeat to process the moving average of frame times
457 for (int i = 0; i < m_numberFramesStored; i++)
458 {
459 // Sum up each frame time in order to calculate the moving
460 // average of frame time
461 totalSumFrameTime += m_totalFrameTimeMilliseconds[i];
462 simulationSumFrameTime +=
463 m_simulationFrameTimeMilliseconds[i];
464 physicsSumFrameTime += m_physicsFrameTimeMilliseconds[i];
465 networkSumFrameTime += m_networkFrameTimeMilliseconds[i];
466 }
467
468 // Get the index that represents the current frame based on the next one known; go back
469 // to the last index if next one is stated to restart at 0
470 if (m_nextLocation == 0)
471 currentFrame = m_numberFramesStored - 1;
472 else
473 currentFrame = m_nextLocation - 1;
474
475 // Calculate the frame dilation; which is currently based on the ratio between the sum of the
476 // physics and simulation rate, and the set minimum time to run a scene's frame
477 frameDilation = (float)(m_simulationFrameTimeMilliseconds[currentFrame] +
478 m_physicsFrameTimeMilliseconds[currentFrame]) / m_scene.MinFrameTicks;
479
480 // ORIGINAL code commented out until we have time to add our own
481 sb[0].StatID = (uint) Stats.TimeDilation; 471 sb[0].StatID = (uint) Stats.TimeDilation;
482 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); 472 sb[0].StatValue = (Single.IsNaN(timeDilation)) ? 0.0f : (float)Math.Round(timeDilation,3);
483 473
484 sb[1].StatID = (uint) Stats.SimFPS; 474 sb[1].StatID = (uint) Stats.SimFPS;
485 sb[1].StatValue = reportedFPS / m_statsUpdateFactor; 475 sb[1].StatValue = (float)Math.Round(reportedFPS,1);;
486 476
487 sb[2].StatID = (uint) Stats.PhysicsFPS; 477 sb[2].StatID = (uint) Stats.PhysicsFPS;
488 sb[2].StatValue = physfps / m_statsUpdateFactor; 478 sb[2].StatValue = (float)Math.Round(physfps,1);
489 479
490 sb[3].StatID = (uint) Stats.AgentUpdates; 480 sb[3].StatID = (uint) Stats.AgentUpdates;
491 sb[3].StatValue = (m_agentUpdates / m_statsUpdateFactor); 481 sb[3].StatValue = m_agentUpdates * updateTimeFactor;
492 482
493 sb[4].StatID = (uint) Stats.Agents; 483 sb[4].StatID = (uint) Stats.Agents;
494 sb[4].StatValue = m_rootAgents; 484 sb[4].StatValue = m_rootAgents;
@@ -502,38 +492,32 @@ namespace OpenSim.Region.Framework.Scenes
502 sb[7].StatID = (uint) Stats.ActivePrim; 492 sb[7].StatID = (uint) Stats.ActivePrim;
503 sb[7].StatValue = m_activePrim; 493 sb[7].StatValue = m_activePrim;
504 494
505 // ORIGINAL code commented out until we have time to add our own
506 // statistics to the statistics window
507 sb[8].StatID = (uint)Stats.FrameMS; 495 sb[8].StatID = (uint)Stats.FrameMS;
508 //sb[8].StatValue = m_frameMS / framesUpdated; 496 sb[8].StatValue = totalFrameTime;
509 sb[8].StatValue = (float) totalSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
510 497
511 sb[9].StatID = (uint)Stats.NetMS; 498 sb[9].StatID = (uint)Stats.NetMS;
512 //sb[9].StatValue = m_netMS / framesUpdated; 499 sb[9].StatValue = m_netMS * perframefactor;
513 sb[9].StatValue = (float) networkSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
514 500
515 sb[10].StatID = (uint)Stats.PhysicsMS; 501 sb[10].StatID = (uint)Stats.PhysicsMS;
516 //sb[10].StatValue = m_physicsMS / framesUpdated; 502 sb[10].StatValue = physicsMS;
517 sb[10].StatValue = (float) physicsSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
518 503
519 sb[11].StatID = (uint)Stats.ImageMS ; 504 sb[11].StatID = (uint)Stats.ImageMS ;
520 sb[11].StatValue = m_imageMS / framesUpdated; 505 sb[11].StatValue = m_imageMS * perframefactor;
521 506
522 sb[12].StatID = (uint)Stats.OtherMS; 507 sb[12].StatID = (uint)Stats.OtherMS;
523 //sb[12].StatValue = m_otherMS / framesUpdated; 508 sb[12].StatValue = otherMS;
524 sb[12].StatValue = (float) simulationSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
525 509
526 sb[13].StatID = (uint)Stats.InPacketsPerSecond; 510 sb[13].StatID = (uint)Stats.InPacketsPerSecond;
527 sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); 511 sb[13].StatValue = (float)Math.Round(m_inPacketsPerSecond * updateTimeFactor);
528 512
529 sb[14].StatID = (uint)Stats.OutPacketsPerSecond; 513 sb[14].StatID = (uint)Stats.OutPacketsPerSecond;
530 sb[14].StatValue = (m_outPacketsPerSecond / m_statsUpdateFactor); 514 sb[14].StatValue = (float)Math.Round(m_outPacketsPerSecond * updateTimeFactor);
531 515
532 sb[15].StatID = (uint)Stats.UnAckedBytes; 516 sb[15].StatID = (uint)Stats.UnAckedBytes;
533 sb[15].StatValue = m_unAckedBytes; 517 sb[15].StatValue = m_unAckedBytes;
534 518
535 sb[16].StatID = (uint)Stats.AgentMS; 519 sb[16].StatID = (uint)Stats.AgentMS;
536 sb[16].StatValue = m_agentMS / framesUpdated; 520 sb[16].StatValue = agentMS;
537 521
538 sb[17].StatID = (uint)Stats.PendingDownloads; 522 sb[17].StatID = (uint)Stats.PendingDownloads;
539 sb[17].StatValue = m_pendingDownloads; 523 sb[17].StatValue = m_pendingDownloads;
@@ -544,120 +528,155 @@ namespace OpenSim.Region.Framework.Scenes
544 sb[19].StatID = (uint)Stats.ActiveScripts; 528 sb[19].StatID = (uint)Stats.ActiveScripts;
545 sb[19].StatValue = m_activeScripts; 529 sb[19].StatValue = m_activeScripts;
546 530
547 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; 531 sb[20].StatID = (uint)Stats.SimSleepMs;
548 sb[20].StatValue = m_scriptLinesPerSecond / m_statsUpdateFactor; 532 sb[20].StatValue = sleeptime;
549 533
550 sb[21].StatID = (uint)Stats.SimSpareMs; 534 sb[21].StatID = (uint)Stats.SimSpareMs;
551 sb[21].StatValue = m_spareMS / framesUpdated; 535 sb[21].StatValue = sparetime;
536
537 // this should came from phys engine
538 sb[22].StatID = (uint)Stats.SimPhysicsStepMs;
539 sb[22].StatValue = 20;
540
541 // send the ones we dont have as zeros, to clean viewers state
542 // specially arriving from regions with wrond IDs in use
543
544 sb[23].StatID = (uint)Stats.VirtualSizeKb;
545 sb[23].StatValue = 0;
546
547 sb[24].StatID = (uint)Stats.ResidentSizeKb;
548 sb[24].StatValue = 0;
549
550 sb[25].StatID = (uint)Stats.PendingLocalUploads;
551 sb[25].StatValue = 0;
552
553 sb[26].StatID = (uint)Stats.PhysicsPinnedTasks;
554 sb[26].StatValue = 0;
555
556 sb[27].StatID = (uint)Stats.PhysicsLodTasks;
557 sb[27].StatValue = 0;
552 558
553 // Current ratio between the sum of physics and sim rate, and the 559 sb[28].StatID = (uint)Stats.ScriptEps; // we actuall have this, but not messing array order AGAIN
554 // minimum time to run a scene's frame 560 sb[28].StatValue = (float)Math.Round(m_scriptEventsPerSecond * updateTimeFactor);
555 sb[22].StatID = (uint)Stats.FrameDilation;
556 sb[22].StatValue = frameDilation;
557 561
558 // Current number of users currently attemptint to login to region 562 sb[29].StatID = (uint)Stats.SimAIStepTimeMS;
559 sb[23].StatID = (uint)Stats.UsersLoggingIn; 563 sb[29].StatValue = 0;
560 sb[23].StatValue = m_usersLoggingIn;
561 564
562 // Total number of geometric primitives in the scene 565 sb[30].StatID = (uint)Stats.SimIoPumpTime;
563 sb[24].StatID = (uint)Stats.TotalGeoPrim; 566 sb[30].StatValue = 0;
564 sb[24].StatValue = m_numGeoPrim;
565 567
566 // Total number of mesh objects in the scene 568 sb[31].StatID = (uint)Stats.SimPCTSscriptsRun;
567 sb[25].StatID = (uint)Stats.TotalMesh; 569 sb[31].StatValue = 0;
568 sb[25].StatValue = m_numMesh;
569 570
570 // Current number of threads that XEngine is using 571 sb[32].StatID = (uint)Stats.SimRegionIdle;
571 sb[26].StatID = (uint)Stats.ThreadCount; 572 sb[32].StatValue = 0;
572 sb[26].StatValue = m_inUseThreads;
573 573
574 sb[27].StatID = (uint)Stats.ScriptMS; 574 sb[33].StatID = (uint)Stats.SimRegionIdlePossible;
575 sb[27].StatValue = (numFrames <= 0) ? 0 : ((float)m_scriptMS / numFrames); 575 sb[33].StatValue = 0;
576 576
577 for (int i = 0; i < m_statisticArraySize; i++) 577 sb[34].StatID = (uint)Stats.SimSkippedSillouet_PS;
578 sb[34].StatValue = 0;
579
580 sb[35].StatID = (uint)Stats.SimSkippedCharsPerC;
581 sb[35].StatValue = 0;
582
583 sb[36].StatID = (uint)Stats.SimPhysicsMemory;
584 sb[36].StatValue = 0;
585
586 sb[37].StatID = (uint)Stats.ScriptMS;
587 sb[37].StatValue = scriptTimeMS;
588
589 for (int i = 0; i < m_statisticViewerArraySize; i++)
578 { 590 {
579 lastReportedSimStats[i] = sb[i].StatValue; 591 lastReportedSimStats[i] = sb[i].StatValue;
580 } 592 }
581 593
594
595 // add extra stats for internal use
596
597 for (int i = 0; i < m_statisticExtraArraySize; i++)
598 {
599 sbex[i] = new SimStatsPacket.StatBlock();
600 }
601
602 sbex[0].StatID = (uint)Stats.LSLScriptLinesPerSecond;
603 sbex[0].StatValue = m_scriptLinesPerSecond * updateTimeFactor;
604 lastReportedSimStats[38] = m_scriptLinesPerSecond * updateTimeFactor;
605
606 sbex[1].StatID = (uint)Stats.FrameDilation2;
607 sbex[1].StatValue = (Single.IsNaN(timeDilation)) ? 0.1f : timeDilation;
608 lastReportedSimStats[39] = (Single.IsNaN(timeDilation)) ? 0.1f : timeDilation;
609
610 sbex[2].StatID = (uint)Stats.UsersLoggingIn;
611 sbex[2].StatValue = m_usersLoggingIn;
612 lastReportedSimStats[40] = m_usersLoggingIn;
613
614 sbex[3].StatID = (uint)Stats.TotalGeoPrim;
615 sbex[3].StatValue = m_numGeoPrim;
616 lastReportedSimStats[41] = m_numGeoPrim;
617
618 sbex[4].StatID = (uint)Stats.TotalMesh;
619 sbex[4].StatValue = m_numMesh;
620 lastReportedSimStats[42] = m_numMesh;
621
622 sbex[5].StatID = (uint)Stats.ThreadCount;
623 sbex[5].StatValue = m_inUseThreads;
624 lastReportedSimStats[43] = m_inUseThreads;
625
582 SimStats simStats 626 SimStats simStats
583 = new SimStats( 627 = new SimStats(
584 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity, 628 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity,
585 rb, sb, m_scene.RegionInfo.originRegionID); 629 rb, sb, sbex, m_scene.RegionInfo.originRegionID);
586 630
587 handlerSendStatResult = OnSendStatsResult; 631 handlerSendStatResult = OnSendStatsResult;
588 if (handlerSendStatResult != null) 632 if (handlerSendStatResult != null)
589 { 633 {
590 handlerSendStatResult(simStats); 634 handlerSendStatResult(simStats);
591 } 635 }
592 636
593 // Extra statistics that aren't currently sent to clients 637 // Extra statistics that aren't currently sent to clients
594 lock (m_lastReportedExtraSimStats) 638 if (m_scene.PhysicsScene != null)
595 { 639 {
596 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; 640 lock (m_lastReportedExtraSimStats)
597 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
598
599 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
600
601 if (physicsStats != null)
602 { 641 {
603 foreach (KeyValuePair<string, float> tuple in physicsStats) 642 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates * updateTimeFactor;
643 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
644
645 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
646
647 if (physicsStats != null)
604 { 648 {
605 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second 649 foreach (KeyValuePair<string, float> tuple in physicsStats)
606 // Need to change things so that stats source can indicate whether they are per second or 650 {
607 // per frame. 651 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second
608 if (tuple.Key.EndsWith("MS")) 652 // Need to change things so that stats source can indicate whether they are per second or
609 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / framesUpdated; 653 // per frame.
610 else 654 if (tuple.Key.EndsWith("MS"))
611 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / m_statsUpdateFactor; 655 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value * perframefactor;
656 else
657 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value * updateTimeFactor;
658 }
612 } 659 }
613 } 660 }
614 } 661 }
615 662
663// LastReportedObjectUpdates = m_objectUpdates / m_statsUpdateFactor;
616 ResetValues(); 664 ResetValues();
665 Monitor.Exit(m_statsLock);
617 } 666 }
618 } 667 }
619 668
620 private void ResetValues() 669 private void ResetValues()
621 { 670 {
622 // Reset the number of frames that the physics library has
623 // processed since the last stats report
624 m_numberPhysicsFrames = 0;
625
626 m_timeDilation = 0;
627 m_fps = 0;
628 m_pfps = 0;
629 m_agentUpdates = 0; 671 m_agentUpdates = 0;
630 m_objectUpdates = 0; 672 m_objectUpdates = 0;
631 //m_inPacketsPerSecond = 0;
632 //m_outPacketsPerSecond = 0;
633 m_unAckedBytes = 0; 673 m_unAckedBytes = 0;
634 m_scriptLinesPerSecond = 0; 674 m_scriptEventsPerSecond = 0;
635 675
636 m_frameMS = 0;
637 m_agentMS = 0;
638 m_netMS = 0; 676 m_netMS = 0;
639 m_physicsMS = 0;
640 m_imageMS = 0; 677 m_imageMS = 0;
641 m_otherMS = 0;
642 m_scriptMS = 0;
643 m_spareMS = 0;
644 } 678 }
645 679
646 # region methods called from Scene
647 // The majority of these functions are additive
648 // so that you can easily change the amount of
649 // seconds in between sim stats updates
650
651 public void AddTimeDilation(float td)
652 {
653 //float tdsetting = td;
654 //if (tdsetting > 1.0f)
655 //tdsetting = (tdsetting - (tdsetting - 0.91f));
656
657 //if (tdsetting < 0)
658 //tdsetting = 0.0f;
659 m_timeDilation = td;
660 }
661 680
662 internal void CheckStatSanity() 681 internal void CheckStatSanity()
663 { 682 {
@@ -675,14 +694,44 @@ namespace OpenSim.Region.Framework.Scenes
675 } 694 }
676 } 695 }
677 696
678 public void AddFPS(int frames) 697 # region methods called from Scene
698
699 public void AddFrameStats(float _timeDilation, float _physicsFPS, float _agentMS,
700 float _physicsMS, float _otherMS , float _sleepMS,
701 float _frameMS, float _scriptTimeMS)
679 { 702 {
680 m_fps += frames; 703 lock(m_statsFrameLock)
681 } 704 {
705 m_fps++;
706 m_timeDilation += _timeDilation;
707 m_pfps += _physicsFPS;
708 m_agentMS += _agentMS;
709 m_physicsMS += _physicsMS;
710 m_otherMS += _otherMS;
711 m_sleeptimeMS += _sleepMS;
712 m_frameMS += _frameMS;
713 m_scriptTimeMS += _scriptTimeMS;
714
715 if (_frameMS > SlowFramesStatReportThreshold)
716 SlowFramesStat.Value++;
717
718 m_FrameStatsTS = Util.GetTimeStampMS();
719 }
720 }
682 721
683 public void AddPhysicsFPS(float frames) 722 private void ResetFrameStats()
684 { 723 {
685 m_pfps += frames; 724 m_fps = 0;
725 m_timeDilation = 0.0f;
726 m_pfps = 0.0f;
727 m_agentMS = 0.0f;
728 m_physicsMS = 0.0f;
729 m_otherMS = 0.0f;
730 m_sleeptimeMS = 0.0f;
731 m_frameMS = 0.0f;
732 m_scriptTimeMS = 0.0f;
733
734 m_prevFrameStatsTS = m_FrameStatsTS;
686 } 735 }
687 736
688 public void AddObjectUpdates(int numUpdates) 737 public void AddObjectUpdates(int numUpdates)
@@ -711,77 +760,17 @@ namespace OpenSim.Region.Framework.Scenes
711 if (m_unAckedBytes < 0) m_unAckedBytes = 0; 760 if (m_unAckedBytes < 0) m_unAckedBytes = 0;
712 } 761 }
713 762
714 public void addFrameMS(int ms)
715 {
716 m_frameMS += ms;
717
718 // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
719 // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern).
720 if (ms > SlowFramesStatReportThreshold)
721 SlowFramesStat.Value++;
722 }
723
724 public void AddSpareMS(int ms)
725 {
726 m_spareMS += ms;
727 }
728 763
729 public void addNetMS(int ms) 764 public void addNetMS(float ms)
730 { 765 {
731 m_netMS += ms; 766 m_netMS += ms;
732 } 767 }
733 768
734 public void addAgentMS(int ms) 769 public void addImageMS(float ms)
735 {
736 m_agentMS += ms;
737 }
738
739 public void addPhysicsMS(int ms)
740 {
741 m_physicsMS += ms;
742 }
743
744 public void addImageMS(int ms)
745 { 770 {
746 m_imageMS += ms; 771 m_imageMS += ms;
747 } 772 }
748 773
749 public void addOtherMS(int ms)
750 {
751 m_otherMS += ms;
752 }
753
754 public void AddScriptMS(int ms)
755 {
756 m_scriptMS += ms;
757 }
758
759 public void addPhysicsFrame(int frames)
760 {
761 // Add the number of physics frames to the correct total physics
762 // frames
763 m_numberPhysicsFrames += frames;
764 }
765
766 public void addFrameTimeMilliseconds(double total, double simulation,
767 double physics, double network)
768 {
769 // Save the frame times from the current frame into the appropriate
770 // arrays
771 m_totalFrameTimeMilliseconds[m_nextLocation] = total;
772 m_simulationFrameTimeMilliseconds[m_nextLocation] = simulation;
773 m_physicsFrameTimeMilliseconds[m_nextLocation] = physics;
774 m_networkFrameTimeMilliseconds[m_nextLocation] = network;
775
776 // Update to the next location in the list
777 m_nextLocation++;
778
779 // Since the list will begin to overwrite the oldest frame values
780 // first, the next location needs to loop back to the beginning of the
781 // list whenever it reaches the end
782 m_nextLocation = m_nextLocation % m_numberFramesStored;
783 }
784
785 public void AddPendingDownloads(int count) 774 public void AddPendingDownloads(int count)
786 { 775 {
787 m_pendingDownloads += count; 776 m_pendingDownloads += count;
@@ -792,9 +781,9 @@ namespace OpenSim.Region.Framework.Scenes
792 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads); 781 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads);
793 } 782 }
794 783
795 public void addScriptLines(int count) 784 public void addScriptEvents(int count)
796 { 785 {
797 m_scriptLinesPerSecond += count; 786 m_scriptEventsPerSecond += count;
798 } 787 }
799 788
800 public void AddPacketsStats(int inPackets, int outPackets, int unAckedBytes) 789 public void AddPacketsStats(int inPackets, int outPackets, int unAckedBytes)
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index 3d563a6..506ad24 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.Framework.Scenes
57 public int Height { get { return m_terrainData.SizeY; } } // Y dimension 57 public int Height { get { return m_terrainData.SizeY; } } // Y dimension
58 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension 58 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
59 59
60
60 // Default, not-often-used builder 61 // Default, not-often-used builder
61 public TerrainChannel() 62 public TerrainChannel()
62 { 63 {
@@ -157,7 +158,11 @@ namespace OpenSim.Region.Framework.Scenes
157 { 158 {
158 if (Double.IsNaN(value) || Double.IsInfinity(value)) 159 if (Double.IsNaN(value) || Double.IsInfinity(value))
159 return; 160 return;
160 161 if (value < 0)
162 value = 0;
163 else
164 if (value > 655.35)
165 value = 655.35;
161 m_terrainData[x, y] = (float)value; 166 m_terrainData[x, y] = (float)value;
162 } 167 }
163 } 168 }
@@ -363,8 +368,8 @@ namespace OpenSim.Region.Framework.Scenes
363 public int SizeY; 368 public int SizeY;
364 public int SizeZ; 369 public int SizeZ;
365 public float CompressionFactor; 370 public float CompressionFactor;
366 public int[] Map; 371 public float[] Map;
367 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, int[] pMap) 372 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, float[] pMap)
368 { 373 {
369 Version = 1; 374 Version = 1;
370 SizeX = pX; 375 SizeX = pX;
@@ -395,17 +400,22 @@ namespace OpenSim.Region.Framework.Scenes
395 // Fill the heightmap with the center bump terrain 400 // Fill the heightmap with the center bump terrain
396 private void PinHeadIsland() 401 private void PinHeadIsland()
397 { 402 {
403 float cx = m_terrainData.SizeX * 0.5f;
404 float cy = m_terrainData.SizeY * 0.5f;
405 float h;
398 for (int x = 0; x < Width; x++) 406 for (int x = 0; x < Width; x++)
399 { 407 {
400 for (int y = 0; y < Height; y++) 408 for (int y = 0; y < Height; y++)
401 { 409 {
402 m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 410 // h = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
403 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d); 411 h = 1.0f;
404 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d); 412 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 50) * 0.01d);
405 if (m_terrainData[x, y]< spherFacA) 413 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 100) * 0.001d);
406 m_terrainData[x, y]= spherFacA; 414 if (h < spherFacA)
407 if (m_terrainData[x, y]< spherFacB) 415 h = spherFacA;
408 m_terrainData[x, y] = spherFacB; 416 if (h < spherFacB)
417 h = spherFacB;
418 m_terrainData[x, y] = h;
409 } 419 }
410 } 420 }
411 } 421 }
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
index fc8f8cd..fd65735 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -27,10 +27,13 @@
27 27
28/* Freely adapted from the Aurora version of the terrain compressor. 28/* Freely adapted from the Aurora version of the terrain compressor.
29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/ 29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
30 * Aurora version created from libOpenMetaverse Library terrain compressor
30 */ 31 */
31 32
32using System; 33using System;
34using System.Collections.Generic;
33using System.Reflection; 35using System.Reflection;
36using System.Diagnostics;
34 37
35using log4net; 38using log4net;
36 39
@@ -45,7 +48,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45{ 48{
46 public static class OpenSimTerrainCompressor 49 public static class OpenSimTerrainCompressor
47 { 50 {
48// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 52
50#pragma warning disable 414 53#pragma warning disable 414
51 private static string LogHeader = "[TERRAIN COMPRESSOR]"; 54 private static string LogHeader = "[TERRAIN COMPRESSOR]";
@@ -61,47 +64,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
61 private const int POSITIVE_VALUE = 0x6; 64 private const int POSITIVE_VALUE = 0x6;
62 private const int NEGATIVE_VALUE = 0x7; 65 private const int NEGATIVE_VALUE = 0x7;
63 66
64 private static readonly float[] DequantizeTable16 =
65 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
66
67 private static readonly float[] DequantizeTable32 =
68 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
69 67
70 private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 68// private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
71 //private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; 69 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
72 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
73 private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
74 70
75 private static readonly float[] QuantizeTable16 = 71 private static readonly float[] QuantizeTable16 =
76 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 72 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
73 private static readonly float[] DequantizeTable16 =
74 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
77 75
78 static OpenSimTerrainCompressor() 76 static OpenSimTerrainCompressor()
79 { 77 {
80 // Initialize the decompression tables 78 // Initialize the decompression tables
81 BuildDequantizeTable16(); 79 BuildDequantizeTable16();
82 SetupCosines16(); 80// SetupCosines16();
83 BuildCopyMatrix16(); 81 BuildCopyMatrix16();
84 BuildQuantizeTable16(); 82 BuildQuantizeTable16();
85 } 83 }
86 84
87 // Used to send cloud and wind patches 85 // Used to send cloud and wind patches
88 public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX, 86 public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
89 int pRegionSizeY)
90 { 87 {
91 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 88 LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } };
92 89
93 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader 90 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
94 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize}; 91 { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize };
95 92
96 // Should be enough to fit even the most poorly packed data 93 // Should be enough to fit even the most poorly packed data
97 byte[] data = new byte[patches.Length*Constants.TerrainPatchSize*Constants.TerrainPatchSize*2]; 94 byte[] data = new byte[patches.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
98 BitPack bitpack = new BitPack(data, 0); 95 BitPack bitpack = new BitPack(data, 0);
99 bitpack.PackBits(header.Stride, 16); 96 bitpack.PackBits(header.Stride, 16);
100 bitpack.PackBits(header.PatchSize, 8); 97 bitpack.PackBits(header.PatchSize, 8);
101 bitpack.PackBits(type, 8); 98 bitpack.PackBits(type, 8);
102 99
103 foreach (TerrainPatch t in patches) 100 foreach (TerrainPatch t in patches)
104 CreatePatch(bitpack, t.Data, t.X, t.Y, pRegionSizeX, pRegionSizeY); 101 CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
105 102
106 bitpack.PackBits(END_OF_PATCHES, 8); 103 bitpack.PackBits(END_OF_PATCHES, 8);
107 104
@@ -111,122 +108,131 @@ namespace OpenSim.Region.ClientStack.LindenUDP
111 return layer; 108 return layer;
112 } 109 }
113 110
114 // Create a land packet for a single patch. 111 public static void CreatePatchtStandardSize(BitPack output, float[] patchData, int x, int y)
115 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
116 { 112 {
117 int[] xPieces = new int[1]; 113 TerrainPatch.Header header = PrescanPatch(patchData);
118 int[] yPieces = new int[1]; 114 header.QuantWBits = 136;
119 xPieces[0] = patchX; // patch X dimension
120 yPieces[0] = patchY;
121 115
122 return CreateLandPacket(terrData, xPieces, yPieces); 116 header.PatchIDs = (y & 0x1F);
117 header.PatchIDs += (x << 5);
118
119 int wbits;
120 int[] patch = CompressPatch(patchData, header, 10, out wbits);
121 EncodePatchHeader(output, header, patch, false, ref wbits);
122 EncodePatch(output, patch, 0, wbits);
123 } 123 }
124 124
125 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] xPieces, int[] yPieces) 125 private static TerrainPatch.Header PrescanPatch(float[] patch)
126 { 126 {
127 byte landPacketType = (byte)TerrainPatch.LayerType.Land; 127 TerrainPatch.Header header = new TerrainPatch.Header();
128 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 128 float zmax = -99999999.0f;
129 float zmin = 99999999.0f;
130
131 for (int i = 0; i < Constants.TerrainPatchSize * Constants.TerrainPatchSize; i++)
129 { 132 {
130 landPacketType = (byte)TerrainPatch.LayerType.LandExtended; 133 float val = patch[i];
134 if (val > zmax) zmax = val;
135 if (val < zmin) zmin = val;
131 } 136 }
132 137
133 return CreateLandPacket(terrData, xPieces, yPieces, landPacketType); 138 header.DCOffset = zmin;
139 header.Range = (int)((zmax - zmin) + 1.0f);
140
141 return header;
134 } 142 }
135 143
136 /// <summary> 144 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
137 /// Creates a LayerData packet for compressed land data given a full
138 /// simulator heightmap and an array of indices of patches to compress
139 /// </summary>
140 /// <param name="terrData">
141 /// Terrain data that can result in a meter square heightmap.
142 /// </param>
143 /// <param name="x">
144 /// Array of indexes in the grid of patches
145 /// for this simulator.
146 /// If creating a packet for multiple patches, there will be entries in
147 /// both the X and Y arrays for each of the patches.
148 /// For example if patches 1 and 17 are to be sent,
149 /// x[] = {1,1} and y[] = {0,1} which specifies the patches at
150 /// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
151 /// </param>
152 /// <param name="y">
153 /// Array of indexes in the grid of patches.
154 /// </param>
155 /// <param name="type"></param>
156 /// <returns></returns>
157 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
158 { 145 {
159 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 146 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
147 float oozrange = 1.0f / header.Range;
148 float range = (1 << prequant);
149 float premult = oozrange * range;
160 150
161 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
162 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
163 151
164 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2]; 152 float sub = 0.5f * header.Range + header.DCOffset;
165 BitPack bitpack = new BitPack(data, 0);
166 bitpack.PackBits(header.Stride, 16);
167 bitpack.PackBits(header.PatchSize, 8);
168 bitpack.PackBits(type, 8);
169 153
170 for (int i = 0; i < x.Length; i++) 154 int wordsize = (prequant - 2) & 0x0f;
171 CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]); 155 header.QuantWBits = wordsize;
156 header.QuantWBits |= wordsize << 4;
172 157
173 bitpack.PackBits(END_OF_PATCHES, 8); 158 int k = 0;
159 for (int j = 0; j < Constants.TerrainPatchSize; j++)
160 {
161 for (int i = 0; i < Constants.TerrainPatchSize; i++)
162 block[k++] = (patchData[j * Constants.TerrainPatchSize + i] - sub) * premult;
163 }
174 164
175 layer.LayerData.Data = new byte[bitpack.BytePos + 1]; 165 float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
176 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1); 166 int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
177 167
178 return layer; 168 wbits = (prequant >> 1);
169
170 dct16x16(block, iout, ref wbits);
171
172 return iout;
179 } 173 }
180 174
181 // Unused: left for historical reference. 175 // new using terrain data and patchs indexes
182 public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY) 176 public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] x, int[] y, byte landPacketType)
183 { 177 {
184 TerrainPatch.Header header = PrescanPatch(patchData); 178 List<LayerDataPacket> ret = new List<LayerDataPacket>();
185 header.QuantWBits = 136; 179
186 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 180 //create packet and global header
187 { 181 LayerDataPacket layer = new LayerDataPacket();
188 header.PatchIDs = (y & 0xFFFF); 182
189 header.PatchIDs += (x << 16); 183 layer.LayerID.Type = landPacketType;
190 } 184
191 else 185 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
186 BitPack bitpack = new BitPack(data, 0);
187 bitpack.PackBits(STRIDE, 16);
188 bitpack.PackBits(Constants.TerrainPatchSize, 8);
189 bitpack.PackBits(landPacketType, 8);
190
191 for (int i = 0; i < x.Length; i++)
192 { 192 {
193 header.PatchIDs = (y & 0x1F); 193 CreatePatchFromTerrainData(bitpack, terrData, x[i], y[i]);
194 header.PatchIDs += (x << 5); 194 if (bitpack.BytePos > 980 && i != x.Length - 1)
195 {
196 //finish this packet
197 bitpack.PackBits(END_OF_PATCHES, 8);
198
199 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201 ret.Add(layer);
202
203 // start another
204 layer = new LayerDataPacket();
205 layer.LayerID.Type = landPacketType;
206
207 bitpack = new BitPack(data, 0);
208 bitpack.PackBits(STRIDE, 16);
209 bitpack.PackBits(Constants.TerrainPatchSize, 8);
210 bitpack.PackBits(landPacketType, 8);
211 }
195 } 212 }
196 213
197 // NOTE: No idea what prequant and postquant should be or what they do 214 bitpack.PackBits(END_OF_PATCHES, 8);
198 215
199 int wbits; 216 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200 int[] patch = CompressPatch(patchData, header, 10, out wbits); 217 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201 wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits); 218 ret.Add(layer);
202 EncodePatch(output, patch, 0, wbits); 219
220 return ret;
203 } 221 }
204 222
205 /// <summary> 223 public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
206 /// Add a patch of terrain to a BitPacker
207 /// </summary>
208 /// <param name="output">BitPacker to write the patch to</param>
209 /// <param name="heightmap">
210 /// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
211 /// </param>
212 /// <param name="patchX">
213 /// X offset of the patch to create.
214 /// </param>
215 /// <param name="patchY">
216 /// Y offset of the patch to create.
217 /// </param>
218 /// <param name="pRegionSizeX"></param>
219 /// <param name="pRegionSizeY"></param>
220 public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
221 { 224 {
222 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY); 225 float frange;
223 header.QuantWBits = 136; 226 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
227 header.QuantWBits = 130;
224 228
229 bool largeRegion = false;
225 // If larger than legacy region size, pack patch X and Y info differently. 230 // If larger than legacy region size, pack patch X and Y info differently.
226 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 231 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
227 { 232 {
228 header.PatchIDs = (patchY & 0xFFFF); 233 header.PatchIDs = (patchY & 0xFFFF);
229 header.PatchIDs += (patchX << 16); 234 header.PatchIDs += (patchX << 16);
235 largeRegion = true;
230 } 236 }
231 else 237 else
232 { 238 {
@@ -234,45 +240,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 header.PatchIDs += (patchX << 5); 240 header.PatchIDs += (patchX << 5);
235 } 241 }
236 242
237 // m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}", 243 if (Math.Round((double)frange, 2) == 1.0)
238 // LogHeader, patchX, patchY, header.DCOffset, header.Range); 244 {
245 // flat terrain speed up things
239 246
240 // NOTE: No idea what prequant and postquant should be or what they do 247 header.DCOffset -= 0.5f;
241 int wbits;
242 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
243 wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
244 EncodePatch(output, patch, 0, wbits);
245 }
246 248
247 private static TerrainPatch.Header PrescanPatch(float[] patch) 249 header.QuantWBits = 0x00;
248 { 250 output.PackBits(header.QuantWBits, 8);
249 TerrainPatch.Header header = new TerrainPatch.Header(); 251 output.PackFloat(header.DCOffset);
250 float zmax = -99999999.0f; 252 output.PackBits(1, 16);
251 float zmin = 99999999.0f; 253 if (largeRegion)
254 output.PackBits(header.PatchIDs, 32);
255 else
256 output.PackBits(header.PatchIDs, 10);
252 257
253 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) 258 // and thats all
254 { 259 output.PackBits(ZERO_EOB, 2);
255 float val = patch[i]; 260 return;
256 if (val > zmax) zmax = val;
257 if (val < zmin) zmin = val;
258 } 261 }
259 262
260 header.DCOffset = zmin; 263 int wbits;
261 header.Range = (int) ((zmax - zmin) + 1.0f); 264 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
262 265 EncodePatchHeader(output, header, patch, largeRegion, ref wbits);
263 return header; 266 EncodePatch(output, patch, 0, wbits);
264 } 267 }
265 268
266 // Scan the height info we're returning and return a patch packet header for this patch. 269 // Scan the height info we're returning and return a patch packet header for this patch.
267 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY) 270 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
268 { 271 {
269 TerrainPatch.Header header = new TerrainPatch.Header(); 272 TerrainPatch.Header header = new TerrainPatch.Header();
270 float zmax = -99999999.0f; 273 float zmax = float.MinValue;
271 float zmin = 99999999.0f; 274 float zmin = float.MaxValue;
272 275
273 for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++) 276 int startx = patchX * Constants.TerrainPatchSize;
277 int starty = patchY * Constants.TerrainPatchSize;
278
279 for (int j = starty; j < starty + Constants.TerrainPatchSize; j++)
274 { 280 {
275 for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++) 281 for (int i = startx; i < startx + Constants.TerrainPatchSize; i++)
276 { 282 {
277 float val = terrData[i, j]; 283 float val = terrData[i, j];
278 if (val > zmax) zmax = val; 284 if (val > zmax) zmax = val;
@@ -281,309 +287,430 @@ namespace OpenSim.Region.ClientStack.LindenUDP
281 } 287 }
282 288
283 header.DCOffset = zmin; 289 header.DCOffset = zmin;
284 header.Range = (int)((zmax - zmin) + 1.0f); 290 frange = ((zmax - zmin) + 1.0f);
285 291 header.Range = (int)frange;
286 return header;
287 }
288
289 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
290 {
291 TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
292
293 // Quantized word bits
294 if (header.QuantWBits == END_OF_PATCHES)
295 return header;
296
297 // DC offset
298 header.DCOffset = bitpack.UnpackFloat();
299
300 // Range
301 header.Range = bitpack.UnpackBits(16);
302
303 // Patch IDs (10 bits)
304 header.PatchIDs = bitpack.UnpackBits(10);
305
306 // Word bits
307 header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
308 292
309 return header; 293 return header;
310 } 294 }
311 295
312 private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX, 296 private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, bool largeRegion, ref int wbits)
313 uint pRegionSizeY, int wbits)
314 { 297 {
315 /*
316 int temp;
317 int wbits = (header.QuantWBits & 0x0f) + 2;
318 uint maxWbits = (uint)wbits + 5;
319 uint minWbits = ((uint)wbits >> 1);
320 int wbitsMaxValue;
321 */
322 // goal is to determ minimum number of bits to use so all data fits
323 /*
324 wbits = (int)minWbits;
325 wbitsMaxValue = (1 << wbits);
326
327 for (int i = 0; i < patch.Length; i++)
328 {
329 temp = patch[i];
330 if (temp != 0)
331 {
332 // Get the absolute value
333 if (temp < 0) temp *= -1;
334
335 no coments..
336
337 for (int j = (int)maxWbits; j > (int)minWbits; j--)
338 {
339 if ((temp & (1 << j)) != 0)
340 {
341 if (j > wbits) wbits = j;
342 break;
343 }
344 }
345
346 while (temp > wbitsMaxValue)
347 {
348 wbits++;
349 if (wbits == maxWbits)
350 goto Done;
351 wbitsMaxValue = 1 << wbits;
352 }
353 }
354 }
355
356 Done:
357
358 // wbits += 1;
359 */
360 // better check
361 if (wbits > 17) 298 if (wbits > 17)
362 wbits = 16; 299 wbits = 17;
363 else if (wbits < 3) 300 else if (wbits < 2)
364 wbits = 3; 301 wbits = 2;
365 302
366 header.QuantWBits &= 0xf0; 303 header.QuantWBits &= 0xf0;
367
368 header.QuantWBits |= (wbits - 2); 304 header.QuantWBits |= (wbits - 2);
369 305
370 output.PackBits(header.QuantWBits, 8); 306 output.PackBits(header.QuantWBits, 8);
371 output.PackFloat(header.DCOffset); 307 output.PackFloat(header.DCOffset);
372 output.PackBits(header.Range, 16); 308 output.PackBits(header.Range, 16);
373 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 309 if (largeRegion)
374 output.PackBits(header.PatchIDs, 32); 310 output.PackBits(header.PatchIDs, 32);
375 else 311 else
376 output.PackBits(header.PatchIDs, 10); 312 output.PackBits(header.PatchIDs, 10);
377
378 return wbits;
379 } 313 }
380 314
381 private static void IDCTColumn16(float[] linein, float[] lineout, int column) 315 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
382 { 316 {
383 for (int n = 0; n < Constants.TerrainPatchSize; n++) 317 int maxwbitssize = (1 << wbits) - 1;
384 { 318 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
385 float total = OO_SQRT2*linein[column];
386
387 for (int u = 1; u < Constants.TerrainPatchSize; u++)
388 {
389 int usize = u*Constants.TerrainPatchSize;
390 total += linein[usize + column]*CosineTable16[usize + n];
391 }
392 319
393 lineout[Constants.TerrainPatchSize*n + column] = total; 320 if (postquant > fullSize || postquant < 0)
321 {
322 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
323 return;
394 } 324 }
395 }
396 325
397 private static void IDCTLine16(float[] linein, float[] lineout, int line) 326 if (postquant != 0)
398 { 327 patch[fullSize - postquant] = 0;
399 const float oosob = 2.0f/Constants.TerrainPatchSize;
400 int lineSize = line*Constants.TerrainPatchSize;
401 328
402 for (int n = 0; n < Constants.TerrainPatchSize; n++) 329 int lastZeroindx = fullSize - postquant;
330
331 for (int i = 0; i < fullSize; i++)
403 { 332 {
404 float total = OO_SQRT2*linein[lineSize]; 333 int temp = patch[i];
405 334
406 for (int u = 1; u < Constants.TerrainPatchSize; u++) 335 if (temp == 0)
407 { 336 {
408 total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n]; 337 bool eob = true;
338
339 for (int j = i; j < lastZeroindx; j++)
340 {
341 if (patch[j] != 0)
342 {
343 eob = false;
344 break;
345 }
346 }
347
348 if (eob)
349 {
350 output.PackBits(ZERO_EOB, 2);
351 return;
352 }
353 output.PackBits(ZERO_CODE, 1);
409 } 354 }
355 else
356 {
357 if (temp < 0)
358 {
359 temp *= -1;
360
361 if (temp > maxwbitssize) temp = maxwbitssize;
410 362
411 lineout[lineSize + n] = total*oosob; 363 output.PackBits(NEGATIVE_VALUE, 3);
364 output.PackBits(temp, wbits);
365 }
366 else
367 {
368 if (temp > maxwbitssize) temp = maxwbitssize;
369
370 output.PackBits(POSITIVE_VALUE, 3);
371 output.PackBits(temp, wbits);
372 }
373 }
412 } 374 }
413 } 375 }
414 376
415/* 377 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
416 private static void DCTLine16(float[] linein, float[] lineout, int line) 378 int prequant, out int wbits)
417 { 379 {
418 float total = 0.0f; 380 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
419 int lineSize = line * Constants.TerrainPatchSize; 381 int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
420 382
421 for (int n = 0; n < Constants.TerrainPatchSize; n++) 383 float oozrange = 1.0f / header.Range;
422 { 384 float invprequat = (1 << prequant);
423 total += linein[lineSize + n]; 385 float premult = oozrange * invprequat;
424 }
425 386
426 lineout[lineSize] = OO_SQRT2 * total; 387 float sub = 0.5f * header.Range + header.DCOffset;
427 388
428 int uptr = 0; 389 int wordsize = (prequant - 2) & 0x0f;
429 for (int u = 1; u < Constants.TerrainPatchSize; u++) 390 header.QuantWBits = wordsize;
430 { 391 header.QuantWBits |= wordsize << 4;
431 total = 0.0f;
432 uptr += Constants.TerrainPatchSize;
433 392
434 for (int n = 0; n < Constants.TerrainPatchSize; n++) 393 int k = 0;
394 int startX = patchX * Constants.TerrainPatchSize;
395 int startY = patchY * Constants.TerrainPatchSize;
396 for (int y = startY; y < startY + Constants.TerrainPatchSize; y++)
397 {
398 for (int x = startX; x < startX + Constants.TerrainPatchSize; x++)
435 { 399 {
436 total += linein[lineSize + n] * CosineTable16[uptr + n]; 400 block[k++] = (terrData[x, y] - sub) * premult;
437 } 401 }
438
439 lineout[lineSize + u] = total;
440 } 402 }
403
404 wbits = (prequant >> 1);
405
406 dct16x16(block, iout, ref wbits);
407
408 return iout;
441 } 409 }
442*/
443 410
444 private static void DCTLine16(float[] linein, float[] lineout, int line) 411 #region Initialization
445 {
446 // outputs transpose data (lines exchanged with coluns )
447 // so to save a bit of cpu when doing coluns
448 float total = 0.0f;
449 int lineSize = line*Constants.TerrainPatchSize;
450 412
451 for (int n = 0; n < Constants.TerrainPatchSize; n++) 413 private static void BuildDequantizeTable16()
414 {
415 for (int j = 0; j < Constants.TerrainPatchSize; j++)
452 { 416 {
453 total += linein[lineSize + n]; 417 for (int i = 0; i < Constants.TerrainPatchSize; i++)
418 {
419 DequantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f + 2.0f * (i + j);
420 }
454 } 421 }
422 }
455 423
456 lineout[line] = OO_SQRT2*total; 424 private static void BuildQuantizeTable16()
457 425 {
458 for (int u = Constants.TerrainPatchSize; 426 const float oosob = 2.0f / Constants.TerrainPatchSize;
459 u < Constants.TerrainPatchSize*Constants.TerrainPatchSize; 427 for (int j = 0; j < Constants.TerrainPatchSize; j++)
460 u += Constants.TerrainPatchSize)
461 { 428 {
462 total = 0.0f; 429 for (int i = 0; i < Constants.TerrainPatchSize; i++)
463 for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
464 { 430 {
465 total += linein[ptrn]*CosineTable16[ptru]; 431 QuantizeTable16[j * Constants.TerrainPatchSize + i] = oosob / (1.0f + 2.0f * (i + (float)j));
466 } 432 }
467
468 lineout[line + u] = total;
469 } 433 }
470 } 434 }
471 435
436 private static void BuildCopyMatrix16()
437 {
438 bool diag = false;
439 bool right = true;
440 int i = 0;
441 int j = 0;
442 int count = 0;
443
444 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
445 {
446 CopyMatrix16[j * Constants.TerrainPatchSize + i] = count++;
472 447
473 /* 448 if (!diag)
474 private static void DCTColumn16(float[] linein, int[] lineout, int column)
475 { 449 {
476 float total = 0.0f; 450 if (right)
477 // const float oosob = 2.0f / Constants.TerrainPatchSize;
478
479 for (int n = 0; n < Constants.TerrainPatchSize; n++)
480 { 451 {
481 total += linein[Constants.TerrainPatchSize * n + column]; 452 if (i < Constants.TerrainPatchSize - 1) i++;
482 } 453 else j++;
483
484 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
485 lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
486 454
487 for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize) 455 right = false;
456 diag = true;
457 }
458 else
488 { 459 {
489 total = 0.0f; 460 if (j < Constants.TerrainPatchSize - 1) j++;
490 461 else i++;
491 for (int n = 0; n < Constants.TerrainPatchSize; n++)
492 {
493 total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
494 }
495 462
496 // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); 463 right = true;
497 lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]); 464 diag = true;
498 } 465 }
466 }
467 else
468 {
469 if (right)
470 {
471 i++;
472 j--;
473 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
474 }
475 else
476 {
477 i--;
478 j++;
479 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
480 }
499 } 481 }
482 }
483 }
500 484
501 private static void DCTColumn16(float[] linein, int[] lineout, int column) 485 #endregion Initialization
502 {
503 // input columns are in fact stored in lines now
504 486
505 float total = 0.0f;
506// const float oosob = 2.0f / Constants.TerrainPatchSize;
507 int inlinesptr = Constants.TerrainPatchSize*column;
508 487
509 for (int n = 0; n < Constants.TerrainPatchSize; n++)
510 {
511 total += linein[inlinesptr + n];
512 }
513 488
514 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
515 lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
516 489
517 for (int uptr = Constants.TerrainPatchSize; 490 #region DCT
518 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
519 uptr += Constants.TerrainPatchSize)
520 {
521 total = 0.0f;
522 491
523 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) 492 /* DCT (Discrete Cosine Transform)
524 { 493 adaptation from
525 total += linein[n]*CosineTable16[ptru]; 494 General Purpose 2D,3D FFT (Fast Fourier Transform) Package
526 } 495 by Takuya OOURA (email: ooura@kurims.kyoto-u.ac.jp)
527 496
528// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); 497 -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
529 lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]); 498 [definition]
530 } 499 <case1> Normalized 16x16 IDCT
531 } 500 C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
501 tmp[j1 + j2] * s[j1] * s[j2] *
502 cos(pi*j1*(k1+1/2)/16) *
503 cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
504 (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
505 <case2> Normalized 16x16 DCT
506 C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
507 tmp[j1 + j2] *
508 cos(pi*(j1+1/2)*k1/16) *
509 cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
510 (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
532 */ 511 */
533 512
534 private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits) 513 /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
514 /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
515 /* Wn_kR = cos(pi/2*k/n) */
516 /* Wn_kI = sin(pi/2*k/n) */
517
518 const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
519 const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
520 const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
521 const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
522 const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
523 const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
524 const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
525 const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
526 const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
527 const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
528 const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
529 const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
530 const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
531 const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
532 const float C16_8R = 0.25f * 2.82842712474619f;
533 const float W16_4R = 0.92387953251128675613f;
534 const float W16_4I = 0.38268343236508977173f;
535 const float W16_8R = 0.70710678118654752440f;
536
537 static void dct16x16(float[] a, int[] iout, ref int wbits)
535 { 538 {
536 // input columns are in fact stored in lines now 539 float[] tmp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
537 540
538 bool dowbits = wbits != maxwbits; 541 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
539 int wbitsMaxValue = 1 << wbits; 542 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
543 float xr, xi;
544 float ftmp;
540 545
541 float total = 0.0f; 546 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
542 // const float oosob = 2.0f / Constants.TerrainPatchSize; 547 int itmp;
543 int inlinesptr = Constants.TerrainPatchSize*column; 548 int j, k;
549 int indx;
544 550
545 for (int n = 0; n < Constants.TerrainPatchSize; n++) 551 const int maxwbits = 17; // per header encoding
552 int wbitsMaxValue = 1 << wbits;
553 bool dowbits = wbits < 17;
554
555 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
546 { 556 {
547 total += linein[inlinesptr + n]; 557 x4r = a[0 + j] - a[15 + j];
558 xr = a[0 + j] + a[15 + j];
559 x4i = a[8 + j] - a[7 + j];
560 xi = a[8 + j] + a[7 + j];
561 x0r = xr + xi;
562 x0i = xr - xi;
563 x5r = a[2 + j] - a[13 + j];
564 xr = a[2 + j] + a[13 + j];
565 x5i = a[10 + j] - a[5 + j];
566 xi = a[10 + j] + a[5 + j];
567 x1r = xr + xi;
568 x1i = xr - xi;
569 x6r = a[4 + j] - a[11 + j];
570 xr = a[4 + j] + a[11 + j];
571 x6i = a[12 + j] - a[3 + j];
572 xi = a[12 + j] + a[3 + j];
573 x2r = xr + xi;
574 x2i = xr - xi;
575 x7r = a[6 + j] - a[9 + j];
576 xr = a[6 + j] + a[9 + j];
577 x7i = a[14 + j] - a[1 + j];
578 xi = a[14 + j] + a[1 + j];
579 x3r = xr + xi;
580 x3i = xr - xi;
581 xr = x0r + x2r;
582 xi = x1r + x3r;
583 tmp[k] = C16_8R * (xr + xi); //
584 tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
585 xr = x0r - x2r;
586 xi = x1r - x3r;
587 tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
588 tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
589 x0r = W16_8R * (x1i - x3i);
590 x2r = W16_8R * (x1i + x3i);
591 xr = x0i + x0r;
592 xi = x2r + x2i;
593 tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
594 tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
595 xr = x0i - x0r;
596 xi = x2r - x2i;
597 tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
598 tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
599 xr = W16_8R * (x6r - x6i);
600 xi = W16_8R * (x6i + x6r);
601 x6r = x4r - xr;
602 x6i = x4i - xi;
603 x4r += xr;
604 x4i += xi;
605 xr = W16_4I * x7r - W16_4R * x7i;
606 xi = W16_4I * x7i + W16_4R * x7r;
607 x7r = W16_4R * x5r - W16_4I * x5i;
608 x7i = W16_4R * x5i + W16_4I * x5r;
609 x5r = x7r + xr;
610 x5i = x7i + xi;
611 x7r -= xr;
612 x7i -= xi;
613 xr = x4r + x5r;
614 xi = x5i + x4i;
615 tmp[Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
616 tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
617 xr = x4r - x5r;
618 xi = x5i - x4i;
619 tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
620 tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
621 xr = x6r - x7i;
622 xi = x7r + x6i;
623 tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
624 tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
625 xr = x6r + x7i;
626 xi = x7r - x6i;
627 tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
628 tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
548 } 629 }
549 630
550 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]); 631 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
551 int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
552 lineout[CopyMatrix16[column]] = tmp;
553
554 if (dowbits)
555 { 632 {
556 if (tmp < 0) tmp *= -1; 633 x4r = tmp[0 + j] - tmp[15 + j];
557 while (tmp > wbitsMaxValue) 634 xr = tmp[0 + j] + tmp[15 + j];
635 x4i = tmp[8 + j] - tmp[7 + j];
636 xi = tmp[8 + j] + tmp[7 + j];
637 x0r = xr + xi;
638 x0i = xr - xi;
639 x5r = tmp[2 + j] - tmp[13 + j];
640 xr = tmp[2 + j] + tmp[13 + j];
641 x5i = tmp[10 + j] - tmp[5 + j];
642 xi = tmp[10 + j] + tmp[5 + j];
643 x1r = xr + xi;
644 x1i = xr - xi;
645 x6r = tmp[4 + j] - tmp[11 + j];
646 xr = tmp[4 + j] + tmp[11 + j];
647 x6i = tmp[12 + j] - tmp[3 + j];
648 xi = tmp[12 + j] + tmp[3 + j];
649 x2r = xr + xi;
650 x2i = xr - xi;
651 x7r = tmp[6 + j] - tmp[9 + j];
652 xr = tmp[6 + j] + tmp[9 + j];
653 x7i = tmp[14 + j] - tmp[1 + j];
654 xi = tmp[14 + j] + tmp[1 + j];
655 x3r = xr + xi;
656 x3i = xr - xi;
657 xr = x0r + x2r;
658 xi = x1r + x3r;
659
660 //tmp[0 + k] = C16_8R * (xr + xi); //
661 ftmp = C16_8R * (xr + xi);
662 itmp = (int)(ftmp * QuantizeTable16[k]);
663 iout[CopyMatrix16[k]] = itmp;
664
665 if (dowbits)
558 { 666 {
559 wbits++; 667 if (itmp < 0) itmp *= -1;
560 wbitsMaxValue = 1 << wbits; 668 while (itmp > wbitsMaxValue)
561 if (wbits == maxwbits)
562 { 669 {
563 dowbits = false; 670 wbits++;
564 break; 671 wbitsMaxValue = 1 << wbits;
672 if (wbits == maxwbits)
673 {
674 dowbits = false;
675 break;
676 }
565 } 677 }
566 } 678 }
567 }
568 679
569 for (int uptr = Constants.TerrainPatchSize; 680 //tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
570 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize; 681 ftmp = C16_8R * (xr - xi);
571 uptr += Constants.TerrainPatchSize) 682 indx = 8 * Constants.TerrainPatchSize + k;
572 { 683 itmp = (int)(ftmp * QuantizeTable16[indx]);
573 total = 0.0f; 684 iout[CopyMatrix16[indx]] = itmp;
574 685
575 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) 686 if (dowbits)
576 { 687 {
577 total += linein[n]*CosineTable16[ptru]; 688 if (itmp < 0) itmp *= -1;
689 while (itmp > wbitsMaxValue)
690 {
691 wbits++;
692 wbitsMaxValue = 1 << wbits;
693 if (wbits == maxwbits)
694 {
695 dowbits = false;
696 break;
697 }
698 }
578 } 699 }
579 700
580 tmp = (int) (total*QuantizeTable16[uptr + column]); 701 xr = x0r - x2r;
581 lineout[CopyMatrix16[uptr + column]] = tmp; 702 xi = x1r - x3r;
703
704 //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
705 ftmp = C16_4R * xr - C16_4I * xi;
706 indx = 4 * Constants.TerrainPatchSize + k;
707 itmp = (int)(ftmp * QuantizeTable16[indx]);
708 iout[CopyMatrix16[indx]] = itmp;
582 709
583 if (dowbits) 710 if (dowbits)
584 { 711 {
585 if (tmp < 0) tmp *= -1; 712 if (itmp < 0) itmp *= -1;
586 while (tmp > wbitsMaxValue) 713 while (itmp > wbitsMaxValue)
587 { 714 {
588 wbits++; 715 wbits++;
589 wbitsMaxValue = 1 << wbits; 716 wbitsMaxValue = 1 << wbits;
@@ -594,355 +721,605 @@ namespace OpenSim.Region.ClientStack.LindenUDP
594 } 721 }
595 } 722 }
596 } 723 }
597 }
598 return wbits;
599 }
600 724
601 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size) 725 //tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
602 { 726 ftmp = C16_4R * xi + C16_4I * xr;
603 for (int n = 0; n < size*size; n++) 727 indx = 12 * Constants.TerrainPatchSize + k;
604 { 728 itmp = (int)(ftmp * QuantizeTable16[indx]);
605 // ? 729 iout[CopyMatrix16[indx]] = itmp;
606 int temp = bitpack.UnpackBits(1); 730
607 if (temp != 0) 731 if (dowbits)
608 { 732 {
609 // Value or EOB 733 if (itmp < 0) itmp *= -1;
610 temp = bitpack.UnpackBits(1); 734 while (itmp > wbitsMaxValue)
611 if (temp != 0)
612 { 735 {
613 // Value 736 wbits++;
614 temp = bitpack.UnpackBits(1); 737 wbitsMaxValue = 1 << wbits;
615 if (temp != 0) 738 if (wbits == maxwbits)
616 {
617 // Negative
618 temp = bitpack.UnpackBits((int) header.WordBits);
619 patches[n] = temp*-1;
620 }
621 else
622 { 739 {
623 // Positive 740 dowbits = false;
624 temp = bitpack.UnpackBits((int) header.WordBits); 741 break;
625 patches[n] = temp;
626 } 742 }
627 } 743 }
628 else 744 }
745
746 x0r = W16_8R * (x1i - x3i);
747 x2r = W16_8R * (x1i + x3i);
748 xr = x0i + x0r;
749 xi = x2r + x2i;
750
751 //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
752 ftmp = C16_2R * xr - C16_2I * xi;
753 indx = 2 * Constants.TerrainPatchSize + k;
754 itmp = (int)(ftmp * QuantizeTable16[indx]);
755 iout[CopyMatrix16[indx]] = itmp;
756
757 if (dowbits)
758 {
759 if (itmp < 0) itmp *= -1;
760 while (itmp > wbitsMaxValue)
629 { 761 {
630 // Set the rest to zero 762 wbits++;
631 // TODO: This might not be necessary 763 wbitsMaxValue = 1 << wbits;
632 for (int o = n; o < size*size; o++) 764 if (wbits == maxwbits)
633 { 765 {
634 patches[o] = 0; 766 dowbits = false;
767 break;
635 } 768 }
636 break;
637 } 769 }
638 } 770 }
639 else
640 {
641 patches[n] = 0;
642 }
643 }
644 }
645 771
646 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits) 772 //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
647 { 773 ftmp = C16_2R * xi + C16_2I * xr;
648 int maxwbitssize = (1 << wbits) - 1; 774 indx = 14 * Constants.TerrainPatchSize + k;
775 itmp = (int)(ftmp * QuantizeTable16[indx]);
776 iout[CopyMatrix16[indx]] = itmp;
649 777
650 if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0) 778 if (dowbits)
651 { 779 {
652 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error); 780 if (itmp < 0) itmp *= -1;
653 return; 781 while (itmp > wbitsMaxValue)
654 } 782 {
783 wbits++;
784 wbitsMaxValue = 1 << wbits;
785 if (wbits == maxwbits)
786 {
787 dowbits = false;
788 break;
789 }
790 }
791 }
655 792
656 if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0; 793 xr = x0i - x0r;
794 xi = x2r - x2i;
657 795
658 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) 796 //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
659 { 797 ftmp = C16_6R * xr - C16_6I * xi;
660 int temp = patch[i]; 798 indx = 6 * Constants.TerrainPatchSize + k;
799 itmp = (int)(ftmp * QuantizeTable16[indx]);
800 iout[CopyMatrix16[indx]] = itmp;
661 801
662 if (temp == 0) 802 if (dowbits)
663 { 803 {
664 bool eob = true; 804 if (itmp < 0) itmp *= -1;
665 805 while (itmp > wbitsMaxValue)
666 for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
667 { 806 {
668 if (patch[j] != 0) 807 wbits++;
808 wbitsMaxValue = 1 << wbits;
809 if (wbits == maxwbits)
669 { 810 {
670 eob = false; 811 dowbits = false;
671 break; 812 break;
672 } 813 }
673 } 814 }
815 }
674 816
675 if (eob) 817 //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
818 ftmp = C16_6R * xi + C16_6I * xr;
819 indx = 10 * Constants.TerrainPatchSize + k;
820 itmp = (int)(ftmp * QuantizeTable16[indx]);
821 iout[CopyMatrix16[indx]] = itmp;
822
823 if (dowbits)
824 {
825 if (itmp < 0) itmp *= -1;
826 while (itmp > wbitsMaxValue)
676 { 827 {
677 output.PackBits(ZERO_EOB, 2); 828 wbits++;
678 return; 829 wbitsMaxValue = 1 << wbits;
830 if (wbits == maxwbits)
831 {
832 dowbits = false;
833 break;
834 }
679 } 835 }
680 output.PackBits(ZERO_CODE, 1);
681 } 836 }
682 else
683 {
684 if (temp < 0)
685 {
686 temp *= -1;
687 837
688 if (temp > maxwbitssize) temp = maxwbitssize; 838 xr = W16_8R * (x6r - x6i);
839 xi = W16_8R * (x6i + x6r);
840 x6r = x4r - xr;
841 x6i = x4i - xi;
842 x4r += xr;
843 x4i += xi;
844 xr = W16_4I * x7r - W16_4R * x7i;
845 xi = W16_4I * x7i + W16_4R * x7r;
846 x7r = W16_4R * x5r - W16_4I * x5i;
847 x7i = W16_4R * x5i + W16_4I * x5r;
848 x5r = x7r + xr;
849 x5i = x7i + xi;
850 x7r -= xr;
851 x7i -= xi;
852 xr = x4r + x5r;
853 xi = x5i + x4i;
854
855 //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
856 ftmp = C16_1R * xr - C16_1I * xi;
857 indx = Constants.TerrainPatchSize + k;
858 itmp = (int)(ftmp * QuantizeTable16[indx]);
859 iout[CopyMatrix16[indx]] = itmp;
689 860
690 output.PackBits(NEGATIVE_VALUE, 3); 861 if (dowbits)
691 output.PackBits(temp, wbits); 862 {
692 } 863 if (itmp < 0) itmp *= -1;
693 else 864 while (itmp > wbitsMaxValue)
694 { 865 {
695 if (temp > maxwbitssize) temp = maxwbitssize; 866 wbits++;
696 867 wbitsMaxValue = 1 << wbits;
697 output.PackBits(POSITIVE_VALUE, 3); 868 if (wbits == maxwbits)
698 output.PackBits(temp, wbits); 869 {
870 dowbits = false;
871 break;
872 }
699 } 873 }
700 } 874 }
701 }
702 }
703 875
704 public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group) 876 //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
705 { 877 ftmp = C16_1R * xi + C16_1I * xr;
706 float[] block = new float[group.PatchSize*group.PatchSize]; 878 indx = 15 * Constants.TerrainPatchSize + k;
707 float[] output = new float[group.PatchSize*group.PatchSize]; 879 itmp = (int)(ftmp * QuantizeTable16[indx]);
708 int prequant = (header.QuantWBits >> 4) + 2; 880 iout[CopyMatrix16[indx]] = itmp;
709 int quantize = 1 << prequant; 881
710 float ooq = 1.0f/quantize; 882 if (dowbits)
711 float mult = ooq*header.Range;
712 float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
713
714 if (group.PatchSize == Constants.TerrainPatchSize)
715 {
716 for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
717 { 883 {
718 block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n]; 884 if (itmp < 0) itmp *= -1;
885 while (itmp > wbitsMaxValue)
886 {
887 wbits++;
888 wbitsMaxValue = 1 << wbits;
889 if (wbits == maxwbits)
890 {
891 dowbits = false;
892 break;
893 }
894 }
719 } 895 }
720 896
721 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 897 xr = x4r - x5r;
898 xi = x5i - x4i;
722 899
723 for (int o = 0; o < Constants.TerrainPatchSize; o++) 900 //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
724 IDCTColumn16(block, ftemp, o); 901 ftmp = C16_7R * xr - C16_7I * xi;
725 for (int o = 0; o < Constants.TerrainPatchSize; o++) 902 indx = 7 * Constants.TerrainPatchSize + k;
726 IDCTLine16(ftemp, block, o); 903 itmp = (int)(ftmp * QuantizeTable16[indx]);
727 } 904 iout[CopyMatrix16[indx]] = itmp;
728 else 905
729 { 906 if (dowbits)
730 for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
731 { 907 {
732 block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n]; 908 if (itmp < 0) itmp *= -1;
909 while (itmp > wbitsMaxValue)
910 {
911 wbits++;
912 wbitsMaxValue = 1 << wbits;
913 if (wbits == maxwbits)
914 {
915 dowbits = false;
916 break;
917 }
918 }
733 } 919 }
734 920
735 Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error); 921 //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
736 } 922 ftmp = C16_7R * xi + C16_7I * xr;
737 923 indx = 9 * Constants.TerrainPatchSize + k;
738 for (int j = 0; j < block.Length; j++) 924 itmp = (int)(ftmp * QuantizeTable16[indx]);
739 { 925 iout[CopyMatrix16[indx]] = itmp;
740 output[j] = block[j]*mult + addval;
741 }
742
743 return output;
744 }
745 926
746 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits) 927 if (dowbits)
747 { 928 {
748 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 929 if (itmp < 0) itmp *= -1;
749 int wordsize = (prequant - 2) & 0x0f; 930 while (itmp > wbitsMaxValue)
750 float oozrange = 1.0f/header.Range; 931 {
751 float range = (1 << prequant); 932 wbits++;
752 float premult = oozrange*range; 933 wbitsMaxValue = 1 << wbits;
753 float sub = (1 << (prequant - 1)) + header.DCOffset*premult; 934 if (wbits == maxwbits)
935 {
936 dowbits = false;
937 break;
938 }
939 }
940 }
754 941
755 header.QuantWBits = wordsize; 942 xr = x6r - x7i;
756 header.QuantWBits |= wordsize << 4; 943 xi = x7r + x6i;
757 944
758 int k = 0; 945 //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
759 for (int j = 0; j < Constants.TerrainPatchSize; j++) 946 ftmp = C16_5R * xr - C16_5I * xi;
760 { 947 indx = 5 * Constants.TerrainPatchSize + k;
761 for (int i = 0; i < Constants.TerrainPatchSize; i++) 948 itmp = (int)(ftmp * QuantizeTable16[indx]);
762 block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub; 949 iout[CopyMatrix16[indx]] = itmp;
763 }
764 950
765 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 951 if (dowbits)
766 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 952 {
953 if (itmp < 0) itmp *= -1;
954 while (itmp > wbitsMaxValue)
955 {
956 wbits++;
957 wbitsMaxValue = 1 << wbits;
958 if (wbits == maxwbits)
959 {
960 dowbits = false;
961 break;
962 }
963 }
964 }
767 965
966 //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
967 ftmp = C16_5R * xi + C16_5I * xr;
968 indx = 11 * Constants.TerrainPatchSize + k;
969 itmp = (int)(ftmp * QuantizeTable16[indx]);
970 iout[CopyMatrix16[indx]] = itmp;
768 971
769 int maxWbits = prequant + 5; 972 if (dowbits)
770 wbits = (prequant >> 1); 973 {
974 if (itmp < 0) itmp *= -1;
975 while (itmp > wbitsMaxValue)
976 {
977 wbits++;
978 wbitsMaxValue = 1 << wbits;
979 if (wbits == maxwbits)
980 {
981 dowbits = false;
982 break;
983 }
984 }
985 }
771 986
772 for (int o = 0; o < Constants.TerrainPatchSize; o++) 987 xr = x6r + x7i;
773 DCTLine16(block, ftemp, o); 988 xi = x7r - x6i;
774 for (int o = 0; o < Constants.TerrainPatchSize; o++)
775 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
776 989
777 return itemp; 990 //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
778 } 991 ftmp = C16_3R * xr - C16_3I * xi;
992 indx = 3 * Constants.TerrainPatchSize + k;
993 itmp = (int)(ftmp * QuantizeTable16[indx]);
994 iout[CopyMatrix16[indx]] = itmp;
779 995
780 private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits) 996 if (dowbits)
781 { 997 {
782 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 998 if (itmp < 0) itmp *= -1;
783 float oozrange = 1.0f/header.Range; 999 while (itmp > wbitsMaxValue)
784 float range = (1 << prequant); 1000 {
785 float premult = oozrange*range; 1001 wbits++;
786 float sub = (1 << (prequant - 1)) + header.DCOffset*premult; 1002 wbitsMaxValue = 1 << wbits;
787 int wordsize = (prequant - 2) & 0x0f; 1003 if (wbits == maxwbits)
1004 {
1005 dowbits = false;
1006 break;
1007 }
1008 }
1009 }
788 1010
789 header.QuantWBits = wordsize; 1011 //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
790 header.QuantWBits |= wordsize << 4; 1012 ftmp = C16_3R * xi + C16_3I * xr;
1013 indx = 13 * Constants.TerrainPatchSize + k;
1014 itmp = (int)(ftmp * QuantizeTable16[indx]);
1015 iout[CopyMatrix16[indx]] = itmp;
791 1016
792 int k = 0; 1017 if (dowbits)
793 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1018 {
794 { 1019 if (itmp < 0) itmp *= -1;
795 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1020 while (itmp > wbitsMaxValue)
796 block[k++] = patchData[j, i]*premult - sub; 1021 {
1022 wbits++;
1023 wbitsMaxValue = 1 << wbits;
1024 if (wbits == maxwbits)
1025 {
1026 dowbits = false;
1027 break;
1028 }
1029 }
1030 }
797 } 1031 }
1032 }
798 1033
799 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1034 #endregion DCT
800 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
801
802 int maxWbits = prequant + 5;
803 wbits = (prequant >> 1);
804 1035
805 for (int o = 0; o < Constants.TerrainPatchSize; o++) 1036 #region Decode
806 DCTLine16(block, ftemp, o); 1037 /*
807 for (int o = 0; o < Constants.TerrainPatchSize; o++) 1038 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
808 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); 1039 {
1040 TerrainPatch.Header header = new TerrainPatch.Header { QuantWBits = bitpack.UnpackBits(8) };
809 1041
810 return itemp; 1042 // Quantized word bits
811 } 1043 if (header.QuantWBits == END_OF_PATCHES)
1044 return header;
812 1045
813 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header, 1046 // DC offset
814 int prequant, out int wbits) 1047 header.DCOffset = bitpack.UnpackFloat();
815 {
816 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
817 int wordsize = prequant;
818 float oozrange = 1.0f/header.Range;
819 float range = (1 << prequant);
820 float premult = oozrange*range;
821 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
822 1048
823 header.QuantWBits = wordsize - 2; 1049 // Range
824 header.QuantWBits |= (prequant - 2) << 4; 1050 header.Range = bitpack.UnpackBits(16);
825 1051
826 int k = 0; 1052 // Patch IDs (10 bits)
1053 header.PatchIDs = bitpack.UnpackBits(10);
827 1054
828 int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ? 1055 // Word bits
829 (terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY; 1056 header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);
830 yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
831 1057
832 int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ? 1058 return header;
833 (terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX; 1059 }
834 xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize; 1060 */
835 1061
836 for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++) 1062 /*
837 { 1063 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
838 for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
839 { 1064 {
840 block[k++] = terrData[xx, yy] * premult - sub; 1065 for (int n = 0; n < size * size; n++)
1066 {
1067 // ?
1068 int temp = bitpack.UnpackBits(1);
1069 if (temp != 0)
1070 {
1071 // Value or EOB
1072 temp = bitpack.UnpackBits(1);
1073 if (temp != 0)
1074 {
1075 // Value
1076 temp = bitpack.UnpackBits(1);
1077 if (temp != 0)
1078 {
1079 // Negative
1080 temp = bitpack.UnpackBits((int)header.WordBits);
1081 patches[n] = temp * -1;
1082 }
1083 else
1084 {
1085 // Positive
1086 temp = bitpack.UnpackBits((int)header.WordBits);
1087 patches[n] = temp;
1088 }
1089 }
1090 else
1091 {
1092 // Set the rest to zero
1093 // TODO: This might not be necessary
1094 for (int o = n; o < size * size; o++)
1095 {
1096 patches[o] = 0;
1097 }
1098 break;
1099 }
1100 }
1101 else
1102 {
1103 patches[n] = 0;
1104 }
1105 }
841 } 1106 }
842 } 1107 */
843 1108 #region IDCT
844 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1109 /* not in use
845 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1110 private static void IDCTColumn16(float[] linein, float[] lineout, int column)
846
847 int maxWbits = prequant + 5;
848 wbits = (prequant >> 1);
849
850 for (int o = 0; o < Constants.TerrainPatchSize; o++)
851 DCTLine16(block, ftemp, o);
852 for (int o = 0; o < Constants.TerrainPatchSize; o++)
853 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
854
855 return itemp;
856 }
857
858 #region Initialization
859
860 private static void BuildDequantizeTable16()
861 { 1111 {
862 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1112 for (int n = 0; n < Constants.TerrainPatchSize; n++)
863 { 1113 {
864 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1114 float total = OO_SQRT2 * linein[column];
1115
1116 for (int u = 1; u < Constants.TerrainPatchSize; u++)
865 { 1117 {
866 DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j); 1118 int usize = u * Constants.TerrainPatchSize;
1119 total += linein[usize + column] * CosineTable16[usize + n];
867 } 1120 }
1121
1122 lineout[Constants.TerrainPatchSize * n + column] = total;
868 } 1123 }
869 } 1124 }
870 1125
871 private static void BuildQuantizeTable16() 1126 private static void IDCTLine16(float[] linein, float[] lineout, int line)
872 { 1127 {
873 const float oosob = 2.0f/Constants.TerrainPatchSize; 1128 const float oosob = 2.0f / Constants.TerrainPatchSize;
874 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1129 int lineSize = line * Constants.TerrainPatchSize;
1130
1131 for (int n = 0; n < Constants.TerrainPatchSize; n++)
875 { 1132 {
876 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1133 float total = OO_SQRT2 * linein[lineSize];
1134
1135 for (int u = 1; u < Constants.TerrainPatchSize; u++)
877 { 1136 {
878// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j)); 1137 total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
879 QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
880 } 1138 }
1139
1140 lineout[lineSize + n] = total * oosob;
881 } 1141 }
882 } 1142 }
883 1143
1144/*
884 private static void SetupCosines16() 1145 private static void SetupCosines16()
885 { 1146 {
886 const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize; 1147 const float hposz = (float)Math.PI * 0.5f / Constants.TerrainPatchSize;
887 1148
888 for (int u = 0; u < Constants.TerrainPatchSize; u++) 1149 for (int u = 0; u < Constants.TerrainPatchSize; u++)
889 { 1150 {
890 for (int n = 0; n < Constants.TerrainPatchSize; n++) 1151 for (int n = 0; n < Constants.TerrainPatchSize; n++)
891 { 1152 {
892 CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz); 1153 CosineTable16[u * Constants.TerrainPatchSize + n] = (float)Math.Cos((2.0f * n + 1.0f) * u * hposz);
893 } 1154 }
894 } 1155 }
895 } 1156 }
1157*/
1158 //not in use, and still not fixed
1159 /*
1160 static void idct16x16(float[] a)
1161 {
1162 int j;
1163 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
1164 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
1165 float xr, xi;
896 1166
897 private static void BuildCopyMatrix16() 1167 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
898 {
899 bool diag = false;
900 bool right = true;
901 int i = 0;
902 int j = 0;
903 int count = 0;
904
905 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
906 {
907 CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
908
909 if (!diag)
910 {
911 if (right)
912 {
913 if (i < Constants.TerrainPatchSize - 1) i++;
914 else j++;
915
916 right = false;
917 diag = true;
918 }
919 else
920 {
921 if (j < Constants.TerrainPatchSize - 1) j++;
922 else i++;
923
924 right = true;
925 diag = true;
926 }
927 }
928 else
929 {
930 if (right)
931 {
932 i++;
933 j--;
934 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
935 }
936 else
937 {
938 i--;
939 j++;
940 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
941 }
942 }
943 }
944 }
945 1168
946 #endregion Initialization 1169 for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
1170 {
1171 x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
1172 x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
1173 xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
1174 xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
1175 x4r = x5r + xr;
1176 x4i = x5i - xi;
1177 x5r -= xr;
1178 x5i += xi;
1179 x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
1180 x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
1181 xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
1182 xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
1183 x6r = x7r + xr;
1184 x6i = x7i - xi;
1185 x7r -= xr;
1186 x7i += xi;
1187 xr = x4r - x6r;
1188 xi = x4i - x6i;
1189 x4r += x6r;
1190 x4i += x6i;
1191 x6r = W16_8R * (xi + xr);
1192 x6i = W16_8R * (xi - xr);
1193 xr = x5r + x7i;
1194 xi = x5i - x7r;
1195 x5r -= x7i;
1196 x5i += x7r;
1197 x7r = W16_4I * x5r + W16_4R * x5i;
1198 x7i = W16_4I * x5i - W16_4R * x5r;
1199 x5r = W16_4R * xr + W16_4I * xi;
1200 x5i = W16_4R * xi - W16_4I * xr;
1201 xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
1202 xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
1203 x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
1204 x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
1205 x0r = x2r + xr;
1206 x1r = x3r + xi;
1207 x2r -= xr;
1208 x3r -= xi;
1209 x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
1210 x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
1211 x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
1212 x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
1213 xr = x0i - x1i;
1214 xi = x2i + x3i;
1215 x0i += x1i;
1216 x2i -= x3i;
1217 x1i = W16_8R * (xi + xr);
1218 x3i = W16_8R * (xi - xr);
1219 xr = x0r + x0i;
1220 xi = x0r - x0i;
1221 tmp[0 + j] = xr + x4r;
1222 tmp[15 + j] = xr - x4r;
1223 tmp[8 + j] = xi + x4i;
1224 tmp[7 + j] = xi - x4i;
1225 xr = x1r + x1i;
1226 xi = x1r - x1i;
1227 tmp[2 + j] = xr + x5r;
1228 tmp[13 + j] = xr - x5r;
1229 tmp[10 + j] = xi + x5i;
1230 tmp[5 + j] = xi - x5i;
1231 xr = x2r + x2i;
1232 xi = x2r - x2i;
1233 tmp[4 + j] = xr + x6r;
1234 tmp[11 + j] = xr - x6r;
1235 tmp[12 + j] = xi + x6i;
1236 tmp[3 + j] = xi - x6i;
1237 xr = x3r + x3i;
1238 xi = x3r - x3i;
1239 tmp[6 + j] = xr + x7r;
1240 tmp[9 + j] = xr - x7r;
1241 tmp[14 + j] = xi + x7i;
1242 tmp[1 + j] = xi - x7i;
1243 }
1244 for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
1245 {
1246 x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
1247 x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
1248 xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
1249 xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
1250 x4r = x5r + xr;
1251 x4i = x5i - xi;
1252 x5r -= xr;
1253 x5i += xi;
1254 x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
1255 x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
1256 xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
1257 xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
1258 x6r = x7r + xr;
1259 x6i = x7i - xi;
1260 x7r -= xr;
1261 x7i += xi;
1262 xr = x4r - x6r;
1263 xi = x4i - x6i;
1264 x4r += x6r;
1265 x4i += x6i;
1266 x6r = W16_8R * (xi + xr);
1267 x6i = W16_8R * (xi - xr);
1268 xr = x5r + x7i;
1269 xi = x5i - x7r;
1270 x5r -= x7i;
1271 x5i += x7r;
1272 x7r = W16_4I * x5r + W16_4R * x5i;
1273 x7i = W16_4I * x5i - W16_4R * x5r;
1274 x5r = W16_4R * xr + W16_4I * xi;
1275 x5i = W16_4R * xi - W16_4I * xr;
1276 xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
1277 xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
1278 x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
1279 x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
1280 x0r = x2r + xr;
1281 x1r = x3r + xi;
1282 x2r -= xr;
1283 x3r -= xi;
1284 x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
1285 x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
1286 x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
1287 x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
1288 xr = x0i - x1i;
1289 xi = x2i + x3i;
1290 x0i += x1i;
1291 x2i -= x3i;
1292 x1i = W16_8R * (xi + xr);
1293 x3i = W16_8R * (xi - xr);
1294 xr = x0r + x0i;
1295 xi = x0r - x0i;
1296 tmp[j + 0] = xr + x4r;
1297 tmp[j + 15] = xr - x4r;
1298 tmp[j + 8] = xi + x4i;
1299 tmp[j + 7] = xi - x4i;
1300 xr = x1r + x1i;
1301 xi = x1r - x1i;
1302 tmp[j + 2] = xr + x5r;
1303 tmp[j + 13] = xr - x5r;
1304 tmp[j + 10] = xi + x5i;
1305 tmp[j + 5] = xi - x5i;
1306 xr = x2r + x2i;
1307 xi = x2r - x2i;
1308 tmp[j + 4] = xr + x6r;
1309 tmp[j + 11] = xr - x6r;
1310 tmp[j + 12] = xi + x6i;
1311 tmp[j + 3] = xi - x6i;
1312 xr = x3r + x3i;
1313 xi = x3r - x3i;
1314 tmp[j + 6] = xr + x7r;
1315 tmp[j + 9] = xr - x7r;
1316 tmp[j + 14] = xi + x7i;
1317 tmp[j + 1] = xi - x7i;
1318 }
1319 }
1320 */
1321 #endregion IDCT
1322 #endregion Decode
947 } 1323 }
1324
948} 1325}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
index 0b196c1..dc3b717 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
@@ -42,6 +42,7 @@ using OpenSim.Tests.Common;
42 42
43namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
44{ 44{
45 /*
45 /// <summary> 46 /// <summary>
46 /// Test copying of scene objects. 47 /// Test copying of scene objects.
47 /// </summary> 48 /// </summary>
@@ -343,4 +344,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
343 } 344 }
344 } 345 }
345 } 346 }
347 */
346} \ No newline at end of file 348} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 1c396ac..f980209 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -81,8 +81,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
81 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 81 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
82 82
83 TestScene scene = new SceneHelpers().SetupScene(); 83 TestScene scene = new SceneHelpers().SetupScene();
84 SceneHelpers.SetupSceneModules(scene, new PermissionsModule()); 84 IConfigSource configSource = new IniConfigSource();
85 TestClient client = (TestClient)SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 85 IConfig config = configSource.AddConfig("Startup");
86 config.Set("serverside_object_permissions", true);
87 SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() });
88 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
86 89
87 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 90 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
88 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 91 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
@@ -104,9 +107,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
104 107
105 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 108 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
106 Assert.That(retrievedPart2, Is.Null); 109 Assert.That(retrievedPart2, Is.Null);
107
108 Assert.That(client.ReceivedKills.Count, Is.EqualTo(1));
109 Assert.That(client.ReceivedKills[0], Is.EqualTo(soLocalId));
110 } 110 }
111 111
112 /// <summary> 112 /// <summary>
@@ -133,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 SceneHelpers.SetupSceneModules(sceneB, config, etmB); 133 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
134 134
135 // We need this for derez 135 // We need this for derez
136 SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule()); 136 //SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule());
137 137
138 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, ""); 138 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, "");
139 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, ""); 139 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, "");
@@ -153,12 +153,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
153 uint soLocalId = so.LocalId; 153 uint soLocalId = so.LocalId;
154 154
155 sceneA.DeleteSceneObject(so, false); 155 sceneA.DeleteSceneObject(so, false);
156
157 Assert.That(clientA.ReceivedKills.Count, Is.EqualTo(1));
158 Assert.That(clientA.ReceivedKills[0], Is.EqualTo(soLocalId));
159
160 Assert.That(childClientsB[0].ReceivedKills.Count, Is.EqualTo(1));
161 Assert.That(childClientsB[0].ReceivedKills[0], Is.EqualTo(soLocalId));
162 } 156 }
163 157
164 /// <summary> 158 /// <summary>
@@ -177,7 +171,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
177 UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001"); 171 UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001");
178 172
179 TestScene scene = new SceneHelpers().SetupScene(); 173 TestScene scene = new SceneHelpers().SetupScene();
180 SceneHelpers.SetupSceneModules(scene, new PermissionsModule()); 174 IConfigSource configSource = new IniConfigSource();
175 IConfig config = configSource.AddConfig("Startup");
176 config.Set("serverside_object_permissions", true);
177 SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() });
181 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 178 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
182 179
183 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 180 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
@@ -260,4 +257,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
260// Assert.That(retrievedPart, Is.Null); 257// Assert.That(retrievedPart, Is.Null);
261 } 258 }
262 } 259 }
263} \ No newline at end of file 260}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index 975c4d9..9a665f6 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -60,6 +60,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
60 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2)); 60 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2));
61 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3)); 61 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3));
62 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4)); 62 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4));
63
64 Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1));
63 } 65 }
64 66
65 /// <summary> 67 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
index aadf7c6..a92e364 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common;
42namespace OpenSim.Region.Framework.Scenes.Tests 42namespace OpenSim.Region.Framework.Scenes.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectUserGroupTests : OpenSimTestCase 45 public class SceneObjectUserGroupTests
46 { 46 {
47 /// <summary> 47 /// <summary>
48 /// Test share with group object functionality 48 /// Test share with group object functionality
@@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 public void TestShareWithGroup() 52 public void TestShareWithGroup()
53 { 53 {
54 TestHelpers.InMethod(); 54 TestHelpers.InMethod();
55// log4net.Config.XmlConfigurator.Configure();
55 56
56 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 57 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
57 58
@@ -68,7 +69,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
68 69
69 SceneHelpers.SetupSceneModules( 70 SceneHelpers.SetupSceneModules(
70 scene, configSource, new object[] 71 scene, configSource, new object[]
71 { new PermissionsModule(), 72 { new DefaultPermissionsModule(),
72 new GroupsModule(), 73 new GroupsModule(),
73 new MockGroupsServicesConnector() }); 74 new MockGroupsServicesConnector() });
74 75
@@ -79,4 +80,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
79 groupsModule.CreateGroup(client, "group1", "To boldly go", true, UUID.Zero, 5, true, true, true); 80 groupsModule.CreateGroup(client, "group1", "To boldly go", true, UUID.Zero, 5, true, true, true);
80 } 81 }
81 } 82 }
82} \ No newline at end of file 83}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 96d112d..568cd34 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -44,6 +44,7 @@ using OpenSim.Region.CoreModules.World.Serialiser;
44using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 44using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
45using OpenSim.Tests.Common; 45using OpenSim.Tests.Common;
46using GridRegion = OpenSim.Services.Interfaces.GridRegion; 46using GridRegion = OpenSim.Services.Interfaces.GridRegion;
47using OpenSim.Services.Interfaces;
47 48
48namespace OpenSim.Region.Framework.Scenes.Tests 49namespace OpenSim.Region.Framework.Scenes.Tests
49{ 50{
@@ -226,7 +227,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
226 // *** This is the first stage, when a neighbouring region is told that a viewer is about to try and 227 // *** This is the first stage, when a neighbouring region is told that a viewer is about to try and
227 // establish a child scene presence. We pass in the circuit code that the client has to connect with *** 228 // establish a child scene presence. We pass in the circuit code that the client has to connect with ***
228 // XXX: ViaLogin may not be correct here. 229 // XXX: ViaLogin may not be correct here.
229 scene.SimulationService.CreateAgent(null, region, acd, (uint)TeleportFlags.ViaLogin, out reason); 230 EntityTransferContext ctx = new EntityTransferContext();
231 scene.SimulationService.CreateAgent(null, region, acd, (uint)TeleportFlags.ViaLogin, ctx, out reason);
230 232
231 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); 233 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
232 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 234 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@@ -287,4 +289,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
287// Assert.That(childPresence.IsChildAgent, Is.True); 289// Assert.That(childPresence.IsChildAgent, Is.True);
288 } 290 }
289 } 291 }
290} \ No newline at end of file 292}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
index 2e6dc70..aa26767 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
@@ -73,14 +73,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
73 SceneHelpers.SetupSceneModules(scene, capsMod); 73 SceneHelpers.SetupSceneModules(scene, capsMod);
74 74
75 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid); 75 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid);
76 Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null); 76 //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null);
77 77
78 // TODO: Need to add tests for other ICapabiltiesModule methods. 78 // TODO: Need to add tests for other ICapabiltiesModule methods.
79 79
80// scene.IncomingCloseAgent(sp.UUID, false);
81// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
80 scene.CloseAgent(sp.UUID, false); 82 scene.CloseAgent(sp.UUID, false);
81 Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null); 83// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
82 84
83 // TODO: Need to add tests for other ICapabiltiesModule methods. 85 // TODO: Need to add tests for other ICapabiltiesModule methods.
84 } 86 }
85 } 87 }
86} \ No newline at end of file 88}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 7127644..37eec52 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -190,7 +190,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
190 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 190 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
191 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 191 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
192 // IsAdministrator if no permissions module is present is true. 192 // IsAdministrator if no permissions module is present is true.
193 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB); 193// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
194 194
195 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 195 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
196 TestClient tc = new TestClient(acd, sceneA); 196 TestClient tc = new TestClient(acd, sceneA);
@@ -244,4 +244,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
244 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); 244 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
245 } 245 }
246 } 246 }
247} \ No newline at end of file 247}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index b232a44..8b194e6 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -246,4 +246,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
246 Assert.That(m_sp.PhysicsActor, Is.Not.Null); 246 Assert.That(m_sp.PhysicsActor, Is.Not.Null);
247 } 247 }
248 } 248 }
249} \ No newline at end of file 249}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 443ec51..b8f7458 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -282,7 +282,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
282 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 282 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
283 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 283 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
284 // IsAdministrator if no permissions module is present is true. 284 // IsAdministrator if no permissions module is present is true.
285 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB }); 285 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB });
286 286
287 // Shared scene modules 287 // Shared scene modules
288 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 288 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
@@ -447,7 +447,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
447 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 447 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
448 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 448 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
449 // IsAdministrator if no permissions module is present is true. 449 // IsAdministrator if no permissions module is present is true.
450 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB }); 450 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB });
451 451
452 // Shared scene modules 452 // Shared scene modules
453 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 453 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index b01088d..33a630c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -95,7 +95,7 @@ namespace OpenSim.Region.Framework.Tests
95 Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f); 95 Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f);
96 Vector3 rezVel = new Vector3(2, 2, 2); 96 Vector3 rezVel = new Vector3(2, 2, 2);
97 97
98 scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0); 98 scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0,false);
99 99
100 SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso"); 100 SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso");
101 101
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..7bbf1bd 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,202 +27,307 @@
27 27
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic;
30using log4net; 31using log4net;
31using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
33 35
34namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
35{ 37{
36 public class UndoState 38 public class UndoState
37 { 39 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40 const int UNDOEXPIRESECONDS = 300; // undo expire time (nice to have it came from a ini later)
39
40 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero;
42 public Quaternion Rotation = Quaternion.Identity;
43
44 /// <summary>
45 /// Is this undo state for an entire group?
46 /// </summary>
47 public bool ForGroup;
48 41
42 public ObjectChangeData data;
43 public DateTime creationtime;
49 /// <summary> 44 /// <summary>
50 /// Constructor. 45 /// Constructor.
51 /// </summary> 46 /// </summary>
52 /// <param name="part"></param> 47 /// <param name="part"></param>
53 /// <param name="forGroup">True if the undo is for an entire group</param> 48 /// <param name="change">bit field with what is changed</param>
54 public UndoState(SceneObjectPart part, bool forGroup) 49 ///
50 public UndoState(SceneObjectPart part, ObjectChangeType change)
55 { 51 {
56 if (part.ParentID == 0) 52 data = new ObjectChangeData();
57 { 53 data.change = change;
58 ForGroup = forGroup; 54 creationtime = DateTime.UtcNow;
59
60// if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition;
62// else
63// Position = part.OffsetPosition;
64
65// m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 55
68 Rotation = part.RotationOffset; 56 if (part.ParentGroup.RootPart == part)
69 57 {
70// m_log.DebugFormat( 58 if ((change & ObjectChangeType.Position) != 0)
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 59 data.position = part.ParentGroup.AbsolutePosition;
72 60 if ((change & ObjectChangeType.Rotation) != 0)
73 Scale = part.Shape.Scale; 61 data.rotation = part.RotationOffset;
74 62 if ((change & ObjectChangeType.Scale) != 0)
75// m_log.DebugFormat( 63 data.scale = part.Shape.Scale;
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 64 }
78 else 65 else
79 { 66 {
80 Position = part.OffsetPosition; 67 if ((change & ObjectChangeType.Position) != 0)
81// m_log.DebugFormat( 68 data.position = part.OffsetPosition;
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 69 if ((change & ObjectChangeType.Rotation) != 0)
70 data.rotation = part.RotationOffset;
71 if ((change & ObjectChangeType.Scale) != 0)
72 data.scale = part.Shape.Scale;
73 }
74 }
75 /// <summary>
76 /// check if undo or redo is too old
77 /// </summary>
83 78
84 Rotation = part.RotationOffset; 79 public bool checkExpire()
85// m_log.DebugFormat( 80 {
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 81 TimeSpan t = DateTime.UtcNow - creationtime;
82 if (t.Seconds > UNDOEXPIRESECONDS)
83 return true;
84 return false;
85 }
87 86
88 Scale = part.Shape.Scale; 87 /// <summary>
89// m_log.DebugFormat( 88 /// updates undo or redo creation time to now
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 89 /// </summary>
91 } 90 public void updateExpire()
91 {
92 creationtime = DateTime.UtcNow;
92 } 93 }
93 94
94 /// <summary> 95 /// <summary>
95 /// Compare the relevant state in the given part to this state. 96 /// Compare the relevant state in the given part to this state.
96 /// </summary> 97 /// </summary>
97 /// <param name="part"></param> 98 /// <param name="part"></param>
98 /// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns> 99 /// <returns>true what fiels and related data are equal, False otherwise.</returns>
99 public bool Compare(SceneObjectPart part) 100 ///
101 public bool Compare(SceneObjectPart part, ObjectChangeType change)
100 { 102 {
103 if (data.change != change) // if diferent targets, then they are diferent
104 return false;
105
101 if (part != null) 106 if (part != null)
102 { 107 {
103 if (part.ParentID == 0) 108 if (part.ParentID == 0)
104 return 109 {
105 Position == part.ParentGroup.AbsolutePosition 110 if ((change & ObjectChangeType.Position) != 0 && data.position != part.ParentGroup.AbsolutePosition)
106 && Rotation == part.RotationOffset 111 return false;
107 && Scale == part.Shape.Scale; 112 }
108 else 113 else
109 return 114 {
110 Position == part.OffsetPosition 115 if ((change & ObjectChangeType.Position) != 0 && data.position != part.OffsetPosition)
111 && Rotation == part.RotationOffset 116 return false;
112 && Scale == part.Shape.Scale; 117 }
113 } 118
119 if ((change & ObjectChangeType.Rotation) != 0 && data.rotation != part.RotationOffset)
120 return false;
121 if ((change & ObjectChangeType.Rotation) != 0 && data.scale == part.Shape.Scale)
122 return false;
123 return true;
114 124
125 }
115 return false; 126 return false;
116 } 127 }
117 128
118 public void PlaybackState(SceneObjectPart part) 129 /// <summary>
130 /// executes the undo or redo to a part or its group
131 /// </summary>
132 /// <param name="part"></param>
133 ///
134
135 public void PlayState(SceneObjectPart part)
119 { 136 {
120 part.Undoing = true; 137 part.Undoing = true;
121 138
122 if (part.ParentID == 0) 139 SceneObjectGroup grp = part.ParentGroup;
123 {
124// m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId);
127 140
128 if (Position != Vector3.Zero) 141 if (grp != null)
129 { 142 {
130 if (ForGroup) 143 grp.doChangeObject(part, data);
131 part.ParentGroup.AbsolutePosition = Position; 144 }
132 else 145 part.Undoing = false;
133 part.ParentGroup.UpdateRootPosition(Position); 146 }
134 } 147 }
135 148
136// m_log.DebugFormat( 149 public class UndoRedoState
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 150 {
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 151 int size;
152 public LinkedList<UndoState> m_redo = new LinkedList<UndoState>();
153 public LinkedList<UndoState> m_undo = new LinkedList<UndoState>();
139 154
140 if (ForGroup) 155 /// <summary>
141 part.UpdateRotation(Rotation); 156 /// creates a new UndoRedoState with default states memory size
142 else 157 /// </summary>
143 part.ParentGroup.UpdateRootRotation(Rotation);
144 158
145 if (Scale != Vector3.Zero) 159 public UndoRedoState()
146 { 160 {
147// m_log.DebugFormat( 161 size = 5;
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 162 }
149// part.Shape.Scale, Scale, part.Name, part.LocalId);
150 163
151 if (ForGroup) 164 /// <summary>
152 part.ParentGroup.GroupResize(Scale); 165 /// creates a new UndoRedoState with states memory having indicated size
153 else 166 /// </summary>
154 part.Resize(Scale); 167 /// <param name="size"></param>
155 }
156 168
157 part.ParentGroup.ScheduleGroupForTerseUpdate(); 169 public UndoRedoState(int _size)
158 } 170 {
171 if (_size < 3)
172 size = 3;
159 else 173 else
160 { 174 size = _size;
161 // Note: Updating these properties on sop automatically schedules an update if needed 175 }
162 if (Position != Vector3.Zero)
163 {
164// m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId);
167 176
168 part.OffsetPosition = Position; 177 /// <summary>
169 } 178 /// returns number of undo entries in memory
179 /// </summary>
170 180
171// m_log.DebugFormat( 181 public int Count
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 182 {
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 183 get { return m_undo.Count; }
184 }
174 185
175 part.UpdateRotation(Rotation); 186 /// <summary>
187 /// clears all undo and redo entries
188 /// </summary>
176 189
177 if (Scale != Vector3.Zero) 190 public void Clear()
191 {
192 m_undo.Clear();
193 m_redo.Clear();
194 }
195
196 /// <summary>
197 /// adds a new state undo to part or its group, with changes indicated by what bits
198 /// </summary>
199 /// <param name="part"></param>
200 /// <param name="change">bit field with what is changed</param>
201
202 public void StoreUndo(SceneObjectPart part, ObjectChangeType change)
203 {
204 lock (m_undo)
205 {
206 UndoState last;
207
208 if (m_redo.Count > 0) // last code seems to clear redo on every new undo
178 { 209 {
179// m_log.DebugFormat( 210 m_redo.Clear();
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 211 }
181// part.Shape.Scale, Scale, part.Name, part.LocalId);
182 212
183 part.Resize(Scale); 213 if (m_undo.Count > 0)
214 {
215 // check expired entry
216 last = m_undo.First.Value;
217 if (last != null && last.checkExpire())
218 m_undo.Clear();
219 else
220 {
221 // see if we actually have a change
222 if (last != null)
223 {
224 if (last.Compare(part, change))
225 return;
226 }
227 }
184 } 228 }
185 }
186 229
187 part.Undoing = false; 230 // limite size
231 while (m_undo.Count >= size)
232 m_undo.RemoveLast();
233
234 UndoState nUndo = new UndoState(part, change);
235 m_undo.AddFirst(nUndo);
236 }
188 } 237 }
189 238
190 public void PlayfwdState(SceneObjectPart part) 239 /// <summary>
191 { 240 /// executes last state undo to part or its group
192 part.Undoing = true; 241 /// current state is pushed into redo
242 /// </summary>
243 /// <param name="part"></param>
193 244
194 if (part.ParentID == 0) 245 public void Undo(SceneObjectPart part)
246 {
247 lock (m_undo)
195 { 248 {
196 if (Position != Vector3.Zero) 249 UndoState nUndo;
197 part.ParentGroup.AbsolutePosition = Position;
198
199 if (Rotation != Quaternion.Identity)
200 part.UpdateRotation(Rotation);
201 250
202 if (Scale != Vector3.Zero) 251 // expire redo
252 if (m_redo.Count > 0)
203 { 253 {
204 if (ForGroup) 254 nUndo = m_redo.First.Value;
205 part.ParentGroup.GroupResize(Scale); 255 if (nUndo != null && nUndo.checkExpire())
206 else 256 m_redo.Clear();
207 part.Resize(Scale);
208 } 257 }
209 258
210 part.ParentGroup.ScheduleGroupForTerseUpdate(); 259 if (m_undo.Count > 0)
260 {
261 UndoState goback = m_undo.First.Value;
262 // check expired
263 if (goback != null && goback.checkExpire())
264 {
265 m_undo.Clear();
266 return;
267 }
268
269 if (goback != null)
270 {
271 m_undo.RemoveFirst();
272
273 // redo limite size
274 while (m_redo.Count >= size)
275 m_redo.RemoveLast();
276
277 nUndo = new UndoState(part, goback.data.change); // new value in part should it be full goback copy?
278 m_redo.AddFirst(nUndo);
279
280 goback.PlayState(part);
281 }
282 }
211 } 283 }
212 else 284 }
285
286 /// <summary>
287 /// executes last state redo to part or its group
288 /// current state is pushed into undo
289 /// </summary>
290 /// <param name="part"></param>
291
292 public void Redo(SceneObjectPart part)
293 {
294 lock (m_undo)
213 { 295 {
214 // Note: Updating these properties on sop automatically schedules an update if needed 296 UndoState nUndo;
215 if (Position != Vector3.Zero)
216 part.OffsetPosition = Position;
217 297
218 if (Rotation != Quaternion.Identity) 298 // expire undo
219 part.UpdateRotation(Rotation); 299 if (m_undo.Count > 0)
300 {
301 nUndo = m_undo.First.Value;
302 if (nUndo != null && nUndo.checkExpire())
303 m_undo.Clear();
304 }
220 305
221 if (Scale != Vector3.Zero) 306 if (m_redo.Count > 0)
222 part.Resize(Scale); 307 {
308 UndoState gofwd = m_redo.First.Value;
309 // check expired
310 if (gofwd != null && gofwd.checkExpire())
311 {
312 m_redo.Clear();
313 return;
314 }
315
316 if (gofwd != null)
317 {
318 m_redo.RemoveFirst();
319
320 // limite undo size
321 while (m_undo.Count >= size)
322 m_undo.RemoveLast();
323
324 nUndo = new UndoState(part, gofwd.data.change); // new value in part should it be full gofwd copy?
325 m_undo.AddFirst(nUndo);
326
327 gofwd.PlayState(part);
328 }
329 }
223 } 330 }
224
225 part.Undoing = false;
226 } 331 }
227 } 332 }
228 333
@@ -247,4 +352,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 352 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 353 }
249 } 354 }
250} \ No newline at end of file 355}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 9ec4e1d..d8928ee 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -126,7 +126,6 @@ namespace OpenSim.Region.Framework.Scenes
126// m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid); 126// m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid);
127 127
128 m_assetUuidsToInspect.Enqueue(uuid); 128 m_assetUuidsToInspect.Enqueue(uuid);
129
130 return true; 129 return true;
131 } 130 }
132 131
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 6fe86b2..6611744 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -58,6 +58,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
58 58
59 public ISceneAgent SceneAgent { get; set; } 59 public ISceneAgent SceneAgent { get; set; }
60 60
61 public int PingTimeMS { get { return 0; } }
62
61 private string m_username; 63 private string m_username;
62 private string m_nick; 64 private string m_nick;
63 65
@@ -66,6 +68,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
66 68
67 private bool m_connected = true; 69 private bool m_connected = true;
68 70
71 public List<uint> SelectedObjects {get; private set;}
72
69 public IRCClientView(TcpClient client, Scene scene) 73 public IRCClientView(TcpClient client, Scene scene)
70 { 74 {
71 m_client = client; 75 m_client = client;
@@ -671,6 +675,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
671 public event ObjectDrop OnObjectDrop; 675 public event ObjectDrop OnObjectDrop;
672 public event StartAnim OnStartAnim; 676 public event StartAnim OnStartAnim;
673 public event StopAnim OnStopAnim; 677 public event StopAnim OnStopAnim;
678 public event ChangeAnim OnChangeAnim;
674 public event LinkObjects OnLinkObjects; 679 public event LinkObjects OnLinkObjects;
675 public event DelinkObjects OnDelinkObjects; 680 public event DelinkObjects OnDelinkObjects;
676 public event RequestMapBlocks OnRequestMapBlocks; 681 public event RequestMapBlocks OnRequestMapBlocks;
@@ -717,6 +722,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
717 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; 722 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
718 public event UpdatePrimFlags OnUpdatePrimFlags; 723 public event UpdatePrimFlags OnUpdatePrimFlags;
719 public event UpdatePrimTexture OnUpdatePrimTexture; 724 public event UpdatePrimTexture OnUpdatePrimTexture;
725 public event ClientChangeObject onClientChangeObject;
720 public event UpdateVector OnUpdatePrimGroupPosition; 726 public event UpdateVector OnUpdatePrimGroupPosition;
721 public event UpdateVector OnUpdatePrimSinglePosition; 727 public event UpdateVector OnUpdatePrimSinglePosition;
722 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 728 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -821,6 +827,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
821 public event ObjectOwner OnObjectOwner; 827 public event ObjectOwner OnObjectOwner;
822 public event DirPlacesQuery OnDirPlacesQuery; 828 public event DirPlacesQuery OnDirPlacesQuery;
823 public event DirFindQuery OnDirFindQuery; 829 public event DirFindQuery OnDirFindQuery;
830 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
824 public event DirLandQuery OnDirLandQuery; 831 public event DirLandQuery OnDirLandQuery;
825 public event DirPopularQuery OnDirPopularQuery; 832 public event DirPopularQuery OnDirPopularQuery;
826 public event DirClassifiedQuery OnDirClassifiedQuery; 833 public event DirClassifiedQuery OnDirClassifiedQuery;
@@ -837,7 +844,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
837 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 844 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
838 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 845 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
839 public event ClassifiedDelete OnClassifiedDelete; 846 public event ClassifiedDelete OnClassifiedDelete;
840 public event ClassifiedDelete OnClassifiedGodDelete; 847 public event ClassifiedGodDelete OnClassifiedGodDelete;
841 public event EventNotificationAddRequest OnEventNotificationAddRequest; 848 public event EventNotificationAddRequest OnEventNotificationAddRequest;
842 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 849 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
843 public event EventGodDelete OnEventGodDelete; 850 public event EventGodDelete OnEventGodDelete;
@@ -867,10 +874,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
867 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 874 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
868 public event SimWideDeletesDelegate OnSimWideDeletes; 875 public event SimWideDeletesDelegate OnSimWideDeletes;
869 public event SendPostcard OnSendPostcard; 876 public event SendPostcard OnSendPostcard;
877 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
870 public event MuteListEntryUpdate OnUpdateMuteListEntry; 878 public event MuteListEntryUpdate OnUpdateMuteListEntry;
871 public event MuteListEntryRemove OnRemoveMuteListEntry; 879 public event MuteListEntryRemove OnRemoveMuteListEntry;
872 public event GodlikeMessage onGodlikeMessage; 880 public event GodlikeMessage onGodlikeMessage;
873 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 881 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
882 public event GenericCall2 OnUpdateThrottles;
874 883
875#pragma warning restore 67 884#pragma warning restore 67
876 885
@@ -888,10 +897,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
888 897
889 public void Close() 898 public void Close()
890 { 899 {
891 Close(false); 900 Close(true, false);
892 } 901 }
893 902
894 public void Close(bool force) 903 public void Close(bool sendStop, bool force)
895 { 904 {
896 Disconnect(); 905 Disconnect();
897 } 906 }
@@ -988,6 +997,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
988 997
989 } 998 }
990 999
1000 public virtual bool CanSendLayerData()
1001 {
1002 return false;
1003 }
1004
991 public void SendLayerData(float[] map) 1005 public void SendLayerData(float[] map)
992 { 1006 {
993 1007
@@ -1104,7 +1118,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1104 1118
1105 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 1119 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
1106 { 1120 {
1107 1121
1122 }
1123
1124 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
1125 {
1126
1108 } 1127 }
1109 1128
1110 public void SendRemoveInventoryItem(UUID itemID) 1129 public void SendRemoveInventoryItem(UUID itemID)
@@ -1127,7 +1146,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1127 1146
1128 } 1147 }
1129 1148
1130 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 1149 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
1131 { 1150 {
1132 1151
1133 } 1152 }
@@ -1356,6 +1375,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1356 1375
1357 } 1376 }
1358 1377
1378 public void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY)
1379 {
1380 }
1381
1359 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) 1382 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
1360 { 1383 {
1361 1384
@@ -1421,6 +1444,16 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1421 1444
1422 } 1445 }
1423 1446
1447 public virtual void SetChildAgentThrottle(byte[] throttle,float factor)
1448 {
1449
1450 }
1451
1452 public void SetAgentThrottleSilent(int throttle, int setting)
1453 {
1454
1455
1456 }
1424 public byte[] GetThrottlesPacked(float multiplier) 1457 public byte[] GetThrottlesPacked(float multiplier)
1425 { 1458 {
1426 return new byte[0]; 1459 return new byte[0];
@@ -1544,7 +1577,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1544 1577
1545 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data) 1578 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data)
1546 { 1579 {
1547 1580
1581 }
1582
1583 public void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data)
1584 {
1585
1548 } 1586 }
1549 1587
1550 public void SendOfferCallingCard(UUID srcID, UUID transactionID) 1588 public void SendOfferCallingCard(UUID srcID, UUID transactionID)
@@ -1687,5 +1725,13 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1687 { 1725 {
1688 } 1726 }
1689 1727
1728 public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
1729 {
1730 }
1731
1732 public int GetAgentThrottleSilent(int throttle)
1733 {
1734 return 0;
1735 }
1690 } 1736 }
1691} 1737}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs
index 84211a9..5c45e4d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs
@@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Animation; 43using OpenSim.Region.Framework.Scenes.Animation;
44using OpenSim.Services.Interfaces; 44using OpenSim.Services.Interfaces;
45using AnimationSet = OpenSim.Region.Framework.Scenes.Animation.AnimationSet;
45 46
46namespace OpenSim.Region.OptionalModules.Avatar.Animations 47namespace OpenSim.Region.OptionalModules.Avatar.Animations
47{ 48{
@@ -197,4 +198,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Animations
197 sb.Append("\n"); 198 sb.Append("\n");
198 } 199 }
199 } 200 }
200} \ No newline at end of file 201}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
index 535bf67..c53a762 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -184,7 +184,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
184 hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); 184 hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
185 } 185 }
186 186
187 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, false, true) ? 1 : 0; 187 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, false, false, true) ? 1 : 0;
188 } 188 }
189 } 189 }
190} 190}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
index b5d9fda..73215cb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
48 private static readonly ILog m_log = 48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private static Regex arg = new Regex(@"\[[^\[\]]*\]"); 51 private static Regex arg = new Regex(@"(?<!\\)\[[^\[\]]*(?<!\\)\]");
52 private static int _idk_ = 0; 52 private static int _idk_ = 0;
53 private static int DEBUG_CHANNEL = 2147483647; 53 private static int DEBUG_CHANNEL = 2147483647;
54 54
@@ -499,6 +499,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
499 // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result); 499 // m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result);
500 } 500 }
501 501
502 // Now we unescape the literal brackets
503 result = result.Replace(@"\[","[").Replace(@"\]","]");
504
502 // m_log.DebugFormat("[IRC-Channel] Parse[3]: {0}", result); 505 // m_log.DebugFormat("[IRC-Channel] Parse[3]: {0}", result);
503 return result; 506 return result;
504 507
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index 6985371..5b9a5b5 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -368,11 +368,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
368 m_writer.Flush(); 368 m_writer.Flush();
369 m_writer.WriteLine(m_user); 369 m_writer.WriteLine(m_user);
370 m_writer.Flush(); 370 m_writer.Flush();
371 m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel));
372 m_writer.Flush();
373
374 m_log.InfoFormat("[IRC-Connector-{0}]: {1} has asked to join {2}", idn, m_nick, m_ircChannel);
375
376 } 371 }
377 catch (Exception e) 372 catch (Exception e)
378 { 373 {
@@ -521,7 +516,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
521 c.Message = data["msg"]; 516 c.Message = data["msg"];
522 c.Type = ChatTypeEnum.Region; 517 c.Type = ChatTypeEnum.Region;
523 c.Position = CenterOfRegion; 518 c.Position = CenterOfRegion;
524 c.From = data["nick"]; 519 c.From = data["nick"] + "@IRC";
525 c.Sender = null; 520 c.Sender = null;
526 c.SenderUUID = UUID.Zero; 521 c.SenderUUID = UUID.Zero;
527 522
@@ -659,6 +654,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
659 version = commArgs[2]; 654 version = commArgs[2];
660 usermod = commArgs[3]; 655 usermod = commArgs[3];
661 chanmod = commArgs[4]; 656 chanmod = commArgs[4];
657
658 m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel));
659 m_writer.Flush();
660 m_log.InfoFormat("[IRC-Connector-{0}]: sent request to join {1} ", idn, m_ircChannel);
661
662 break; 662 break;
663 case "005": // Server information 663 case "005": // Server information
664 break; 664 break;
@@ -721,11 +721,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
721 case "PONG": 721 case "PONG":
722 break; 722 break;
723 case "JOIN": 723 case "JOIN":
724 if (m_pending) 724
725 {
726 m_log.InfoFormat("[IRC-Connector-{0}] [{1}] Connected", idn, cmd);
727 m_pending = false;
728 }
729 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); 725 m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
730 eventIrcJoin(pfx, cmd, parms); 726 eventIrcJoin(pfx, cmd, parms);
731 break; 727 break;
@@ -767,7 +763,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
767 if (IrcChannel.StartsWith(":")) 763 if (IrcChannel.StartsWith(":"))
768 IrcChannel = IrcChannel.Substring(1); 764 IrcChannel = IrcChannel.Substring(1);
769 765
770 m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCJoin {1}:{2}", idn, m_server, m_ircChannel); 766 if(IrcChannel == m_ircChannel)
767 {
768 m_log.InfoFormat("[IRC-Connector-{0}] Joined requested channel {1} at {2}", idn, IrcChannel,m_server);
769 m_pending = false;
770 }
771 else
772 m_log.InfoFormat("[IRC-Connector-{0}] Joined unknown channel {1} at {2}", idn, IrcChannel,m_server);
771 BroadcastSim(IrcUser, "/me joins {0}", IrcChannel); 773 BroadcastSim(IrcUser, "/me joins {0}", IrcChannel);
772 } 774 }
773 775
diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
index 4e84364..026ceca 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
@@ -107,7 +107,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends
107 m_scene.AddCommand( 107 m_scene.AddCommand(
108 "Friends", this, "friends show", 108 "Friends", this, "friends show",
109 "friends show [--cache] <first-name> <last-name>", 109 "friends show [--cache] <first-name> <last-name>",
110 "Show the friends for the given user if they exist.\n", 110 "Show the friends for the given user if they exist.",
111 "The --cache option will show locally cached information for that user.", 111 "The --cache option will show locally cached information for that user.",
112 HandleFriendsShowCommand); 112 HandleFriendsShowCommand);
113 } 113 }
@@ -197,4 +197,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends
197 } 197 }
198 } 198 }
199 } 199 }
200} \ No newline at end of file 200}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 45af212..3db0781 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -575,7 +575,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
575 575
576 public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request) 576 public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request)
577 { 577 {
578 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceGetPreloginHTTPHandler called"); 578// m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceGetPreloginHTTPHandler called");
579 579
580 Hashtable response = new Hashtable(); 580 Hashtable response = new Hashtable();
581 response["content_type"] = "text/xml"; 581 response["content_type"] = "text/xml";
@@ -726,7 +726,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
726 726
727 public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request) 727 public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request)
728 { 728 {
729 m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceSigninHTTPHandler called"); 729 //m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called");
730// string requestbody = (string)request["body"]; 730// string requestbody = (string)request["body"];
731// string uri = (string)request["uri"]; 731// string uri = (string)request["uri"];
732// string contenttype = (string)request["content-type"]; 732// string contenttype = (string)request["content-type"];
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index dd44564..f51527e 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -121,6 +121,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
121 121
122 public void Initialise(IConfigSource config) 122 public void Initialise(IConfigSource config)
123 { 123 {
124 MainConsole.Instance.Commands.AddCommand("vivox", false, "vivox debug", "vivox debug <on>|<off>", "Set vivox debugging", HandleDebug);
124 125
125 m_config = config.Configs["VivoxVoice"]; 126 m_config = config.Configs["VivoxVoice"];
126 127
@@ -196,7 +197,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
196 break; 197 break;
197 } 198 }
198 199
199 m_vivoxVoiceAccountApi = String.Format("http://{0}/api2", m_vivoxServer); 200 m_vivoxVoiceAccountApi = String.Format("https://{0}/api2", m_vivoxServer);
200 201
201 // Admin interface required values 202 // Admin interface required values
202 if (String.IsNullOrEmpty(m_vivoxServer) || 203 if (String.IsNullOrEmpty(m_vivoxServer) ||
@@ -475,8 +476,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
475 avatarName = avatar.Name; 476 avatarName = avatar.Name;
476 477
477 m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: scene = {0}, agentID = {1}", scene, agentID); 478 m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: scene = {0}, agentID = {1}", scene, agentID);
478 m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", 479// m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
479 request, path, param); 480// request, path, param);
480 481
481 XmlElement resp; 482 XmlElement resp;
482 bool retry = false; 483 bool retry = false;
@@ -583,7 +584,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
583 584
584 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); 585 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
585 586
586 m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); 587// m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r);
587 588
588 return r; 589 return r;
589 } 590 }
@@ -630,24 +631,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
630 // voice, if all do retrieve or obtain the parcel 631 // voice, if all do retrieve or obtain the parcel
631 // voice channel 632 // voice channel
632 LandData land = scene.GetLandData(avatar.AbsolutePosition); 633 LandData land = scene.GetLandData(avatar.AbsolutePosition);
634 if (land == null)
635 {
636 return "<llsd><undef /></llsd>";
637 }
633 638
634 m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", 639// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
635 scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); 640// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
636 // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: avatar \"{0}\": location: {1} {2} {3}", 641 // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: avatar \"{0}\": location: {1} {2} {3}",
637 // avatarName, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); 642 // avatarName, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
638 643
639 // TODO: EstateSettings don't seem to get propagated... 644 // TODO: EstateSettings don't seem to get propagated...
640 if (!scene.RegionInfo.EstateSettings.AllowVoice) 645 if (!scene.RegionInfo.EstateSettings.AllowVoice)
641 { 646 {
642 m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": voice not enabled in estate settings", 647 //m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": voice not enabled in estate settings",
643 scene.RegionInfo.RegionName); 648 // scene.RegionInfo.RegionName);
644 channel_uri = String.Empty; 649 channel_uri = String.Empty;
645 } 650 }
646 651
647 if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0) 652 if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0)
648 { 653 {
649 m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", 654 //m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel",
650 scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); 655 // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName);
651 channel_uri = String.Empty; 656 channel_uri = String.Empty;
652 } 657 }
653 else 658 else
@@ -662,8 +667,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
662 parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); 667 parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds);
663 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); 668 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
664 669
665 m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", 670// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}",
666 scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); 671// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r);
667 return r; 672 return r;
668 } 673 }
669 catch (Exception e) 674 catch (Exception e)
@@ -690,11 +695,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
690 public string ChatSessionRequest(Scene scene, string request, string path, string param, 695 public string ChatSessionRequest(Scene scene, string request, string path, string param,
691 UUID agentID, Caps caps) 696 UUID agentID, Caps caps)
692 { 697 {
693 ScenePresence avatar = scene.GetScenePresence(agentID); 698// ScenePresence avatar = scene.GetScenePresence(agentID);
694 string avatarName = avatar.Name; 699// string avatarName = avatar.Name;
695 700
696 m_log.DebugFormat("[VivoxVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", 701// m_log.DebugFormat("[VivoxVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}",
697 avatarName, request, path, param); 702// avatarName, request, path, param);
698 return "<llsd>true</llsd>"; 703 return "<llsd>true</llsd>";
699 } 704 }
700 705
@@ -744,7 +749,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
744 return channelUri; 749 return channelUri;
745 } 750 }
746 751
747 private static readonly string m_vivoxLoginPath = "http://{0}/api2/viv_signin.php?userid={1}&pwd={2}"; 752
753 private static readonly string m_vivoxLoginPath = "https://{0}/api2/viv_signin.php?userid={1}&pwd={2}";
748 754
749 /// <summary> 755 /// <summary>
750 /// Perform administrative login for Vivox. 756 /// Perform administrative login for Vivox.
@@ -756,7 +762,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
756 return VivoxCall(requrl, false); 762 return VivoxCall(requrl, false);
757 } 763 }
758 764
759 private static readonly string m_vivoxLogoutPath = "http://{0}/api2/viv_signout.php?auth_token={1}"; 765 private static readonly string m_vivoxLogoutPath = "https://{0}/api2/viv_signout.php?auth_token={1}";
760 766
761 /// <summary> 767 /// <summary>
762 /// Perform administrative logout for Vivox. 768 /// Perform administrative logout for Vivox.
@@ -767,7 +773,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
767 return VivoxCall(requrl, false); 773 return VivoxCall(requrl, false);
768 } 774 }
769 775
770 private static readonly string m_vivoxGetAccountPath = "http://{0}/api2/viv_get_acct.php?auth_token={1}&user_name={2}"; 776
777 private static readonly string m_vivoxGetAccountPath = "https://{0}/api2/viv_get_acct.php?auth_token={1}&user_name={2}";
771 778
772 /// <summary> 779 /// <summary>
773 /// Retrieve account information for the specified user. 780 /// Retrieve account information for the specified user.
@@ -779,7 +786,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
779 return VivoxCall(requrl, true); 786 return VivoxCall(requrl, true);
780 } 787 }
781 788
782 private static readonly string m_vivoxNewAccountPath = "http://{0}/api2/viv_adm_acct_new.php?username={1}&pwd={2}&auth_token={3}"; 789
790 private static readonly string m_vivoxNewAccountPath = "https://{0}/api2/viv_adm_acct_new.php?username={1}&pwd={2}&auth_token={3}";
783 791
784 /// <summary> 792 /// <summary>
785 /// Creates a new account. 793 /// Creates a new account.
@@ -793,7 +801,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
793 return VivoxCall(requrl, true); 801 return VivoxCall(requrl, true);
794 } 802 }
795 803
796 private static readonly string m_vivoxPasswordPath = "http://{0}/api2/viv_adm_password.php?user_name={1}&new_pwd={2}&auth_token={3}"; 804
805 private static readonly string m_vivoxPasswordPath = "https://{0}/api2/viv_adm_password.php?user_name={1}&new_pwd={2}&auth_token={3}";
797 806
798 /// <summary> 807 /// <summary>
799 /// Change the user's password. 808 /// Change the user's password.
@@ -804,7 +813,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
804 return VivoxCall(requrl, true); 813 return VivoxCall(requrl, true);
805 } 814 }
806 815
807 private static readonly string m_vivoxChannelPath = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_name={2}&auth_token={3}"; 816
817 private static readonly string m_vivoxChannelPath = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_name={2}&auth_token={3}";
808 818
809 /// <summary> 819 /// <summary>
810 /// Create a channel. 820 /// Create a channel.
@@ -876,7 +886,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
876 return false; 886 return false;
877 } 887 }
878 888
879 private static readonly string m_vivoxChannelSearchPath = "http://{0}/api2/viv_chan_search.php?cond_channame={1}&auth_token={2}"; 889 private static readonly string m_vivoxChannelSearchPath = "https://{0}/api2/viv_chan_search.php?cond_channame={1}&auth_token={2}";
880 890
881 /// <summary> 891 /// <summary>
882 /// Retrieve a channel. 892 /// Retrieve a channel.
@@ -1019,7 +1029,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1019 return false; 1029 return false;
1020 } 1030 }
1021 1031
1022 // private static readonly string m_vivoxChannelById = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}"; 1032 // private static readonly string m_vivoxChannelById = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}";
1023 1033
1024 // private XmlElement VivoxGetChannelById(string parent, string channelid) 1034 // private XmlElement VivoxGetChannelById(string parent, string channelid)
1025 // { 1035 // {
@@ -1031,7 +1041,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1031 // return VivoxCall(requrl, true); 1041 // return VivoxCall(requrl, true);
1032 // } 1042 // }
1033 1043
1034 private static readonly string m_vivoxChannelDel = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}"; 1044 private static readonly string m_vivoxChannelDel = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}";
1035 1045
1036 /// <summary> 1046 /// <summary>
1037 /// Delete a channel. 1047 /// Delete a channel.
@@ -1044,6 +1054,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1044 /// are required in a later phase. 1054 /// are required in a later phase.
1045 /// In this case the call handles parent and description as optional values. 1055 /// In this case the call handles parent and description as optional values.
1046 /// </summary> 1056 /// </summary>
1057
1047 private XmlElement VivoxDeleteChannel(string parent, string channelid) 1058 private XmlElement VivoxDeleteChannel(string parent, string channelid)
1048 { 1059 {
1049 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken); 1060 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken);
@@ -1054,11 +1065,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1054 return VivoxCall(requrl, true); 1065 return VivoxCall(requrl, true);
1055 } 1066 }
1056 1067
1057 private static readonly string m_vivoxChannelSearch = "http://{0}/api2/viv_chan_search.php?&cond_chanparent={1}&auth_token={2}"; 1068 private static readonly string m_vivoxChannelSearch = "https://{0}/api2/viv_chan_search.php?&cond_chanparent={1}&auth_token={2}";
1058 1069
1059 /// <summary> 1070 /// <summary>
1060 /// Return information on channels in the given directory 1071 /// Return information on channels in the given directory
1061 /// </summary> 1072 /// </summary>
1073
1062 private XmlElement VivoxListChildren(string channelid) 1074 private XmlElement VivoxListChildren(string channelid)
1063 { 1075 {
1064 string requrl = String.Format(m_vivoxChannelSearch, m_vivoxServer, channelid, m_authToken); 1076 string requrl = String.Format(m_vivoxChannelSearch, m_vivoxServer, channelid, m_authToken);
@@ -1124,7 +1136,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1124 try 1136 try
1125 { 1137 {
1126 // Otherwise prepare the request 1138 // Otherwise prepare the request
1127 m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl); 1139 //m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl);
1128 1140
1129 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl); 1141 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl);
1130 1142
@@ -1324,5 +1336,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1324 result = String.Empty; 1336 result = String.Empty;
1325 return false; 1337 return false;
1326 } 1338 }
1339
1340 private void HandleDebug(string module, string[] cmd)
1341 {
1342 if (cmd.Length < 3)
1343 {
1344 MainConsole.Instance.Output("Error: missing on/off flag");
1345 return;
1346 }
1347
1348 if (cmd[2] == "on")
1349 m_dumpXml = true;
1350 else if (cmd[2] == "off")
1351 m_dumpXml = false;
1352 else
1353 MainConsole.Instance.Output("Error: only on and off are supported");
1354 }
1327 } 1355 }
1328} 1356}
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 1565da9..8d587b9 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
79 private IMessageTransferModule m_msgTransferModule; 79 private IMessageTransferModule m_msgTransferModule;
80 80
81 private IGroupsMessagingModule m_groupsMessagingModule; 81 private IGroupsMessagingModule m_groupsMessagingModule;
82 82
83 private IGroupsServicesConnector m_groupData; 83 private IGroupsServicesConnector m_groupData;
84 84
85 // Configuration settings 85 // Configuration settings
@@ -205,10 +205,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
205 } 205 }
206 206
207 scene.EventManager.OnNewClient += OnNewClient; 207 scene.EventManager.OnNewClient += OnNewClient;
208 scene.EventManager.OnMakeRootAgent += OnMakeRoot;
209 scene.EventManager.OnMakeChildAgent += OnMakeChild;
208 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 210 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
209 // The InstantMessageModule itself doesn't do this, 211 scene.EventManager.OnClientClosed += OnClientClosed;
210 // so lets see if things explode if we don't do it
211 // scene.EventManager.OnClientClosed += OnClientClosed;
212 212
213 } 213 }
214 214
@@ -233,7 +233,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
233 if (m_debugEnabled) m_log.Debug("[GROUPS]: Shutting down Groups module."); 233 if (m_debugEnabled) m_log.Debug("[GROUPS]: Shutting down Groups module.");
234 } 234 }
235 235
236 public Type ReplaceableInterface 236 public Type ReplaceableInterface
237 { 237 {
238 get { return null; } 238 get { return null; }
239 } 239 }
@@ -255,84 +255,121 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
255 #endregion 255 #endregion
256 256
257 #region EventHandlers 257 #region EventHandlers
258
259 private void OnMakeRoot(ScenePresence sp)
260 {
261 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
262
263 sp.ControllingClient.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
264 // Used for Notices and Group Invites/Accept/Reject
265 sp.ControllingClient.OnInstantMessage += OnInstantMessage;
266
267 // comented out because some viewers no longer suport it
268 // sp.ControllingClient.AddGenericPacketHandler("avatargroupsrequest", AvatarGroupsRequest);
269
270 // we should send a DataUpdate here for compatibility,
271 // but this is a bad place and a bad thread to do it
272 // also current viewers do ignore it and ask later on a much nicer thread
273 }
274
275 private void OnMakeChild(ScenePresence sp)
276 {
277 if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
278
279 sp.ControllingClient.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest;
280 sp.ControllingClient.OnInstantMessage -= OnInstantMessage;
281 }
282
258 private void OnNewClient(IClientAPI client) 283 private void OnNewClient(IClientAPI client)
259 { 284 {
260 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 285 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
261 286
262 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
263 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; 287 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
264 client.OnRequestAvatarProperties += OnRequestAvatarProperties; 288 client.OnRequestAvatarProperties += OnRequestAvatarProperties;
265 289
266 // Used for Notices and Group Invites/Accept/Reject
267 client.OnInstantMessage += OnInstantMessage;
268 290
269 // Send client their groups information.
270 SendAgentGroupDataUpdate(client, client.AgentId);
271 } 291 }
272 292
293/* this should be the right message to ask for other avatars groups
294
295 private void AvatarGroupsRequest(Object sender, string method, List<String> args)
296 {
297 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
298
299 if (!(sender is IClientAPI))
300 return;
301
302 IClientAPI remoteClient = (IClientAPI)sender;
303
304 UUID avatarID;
305 UUID.TryParse(args[0], out avatarID);
306
307 if (avatarID != UUID.Zero)
308 {
309 GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID);
310 remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups);
311 }
312 }
313*/
314
315 // this should not be used to send groups memberships, but some viewers do expect it
316 // it does send unnecessary memberships, when viewers just want other properties information
273 private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) 317 private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
274 { 318 {
275 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 319 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
276 320
277 //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray();
278 GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); 321 GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID);
279 remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); 322 remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups);
280 } 323 }
281 324
282 /* 325
283 * This becomes very problematic in a shared module. In a shared module you may have more then one 326 private void OnClientClosed(UUID AgentId, Scene scene)
284 * reference to IClientAPI's, one for 0 or 1 root connections, and 0 or more child connections.
285 * The OnClientClosed event does not provide anything to indicate which one of those should be closed
286 * nor does it provide what scene it was from so that the specific reference can be looked up.
287 * The InstantMessageModule.cs does not currently worry about unregistering the handles,
288 * and it should be an issue, since it's the client that references us not the other way around
289 * , so as long as we don't keep a reference to the client laying around, the client can still be GC'ed
290 private void OnClientClosed(UUID AgentId)
291 { 327 {
292 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 328 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
329 if (scene == null)
330 return;
293 331
294 lock (m_ActiveClients) 332 ScenePresence sp = scene.GetScenePresence(AgentId);
333 IClientAPI client = sp.ControllingClient;
334 if (client != null)
295 { 335 {
296 if (m_ActiveClients.ContainsKey(AgentId)) 336 client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest;
337 client.OnRequestAvatarProperties -= OnRequestAvatarProperties;
338 // make child possible not called?
339 client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest;
340 client.OnInstantMessage -= OnInstantMessage;
341 }
342
343/*
344 lock (m_ActiveClients)
297 { 345 {
298 IClientAPI client = m_ActiveClients[AgentId]; 346 if (m_ActiveClients.ContainsKey(AgentId))
299 client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; 347 {
300 client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest; 348 IClientAPI client = m_ActiveClients[AgentId];
301 client.OnDirFindQuery -= OnDirFindQuery; 349 client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest;
302 client.OnInstantMessage -= OnInstantMessage; 350 client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest;
351 client.OnDirFindQuery -= OnDirFindQuery;
352 client.OnInstantMessage -= OnInstantMessage;
303 353
304 m_ActiveClients.Remove(AgentId); 354 m_ActiveClients.Remove(AgentId);
305 } 355 }
306 else 356 else
307 { 357 {
308 if (m_debugEnabled) m_log.WarnFormat("[GROUPS]: Client closed that wasn't registered here."); 358 if (m_debugEnabled) m_log.WarnFormat("[GROUPS]: Client closed that wasn't registered here.");
359 }
309 } 360 }
310 361*/
311
312 }
313 } 362 }
314 */
315 363
316 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) 364 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID)
317 { 365 {
318 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 366 // this a private message for own agent only
319 367 if (dataForAgentID != GetRequestingAgentID(remoteClient))
320 UUID activeGroupID = UUID.Zero; 368 return;
321 string activeGroupTitle = string.Empty;
322 string activeGroupName = string.Empty;
323 ulong activeGroupPowers = (ulong)GroupPowers.None;
324
325 GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient), dataForAgentID);
326 if (membership != null)
327 {
328 activeGroupID = membership.GroupID;
329 activeGroupTitle = membership.GroupTitle;
330 activeGroupPowers = membership.GroupPowers;
331 }
332
333 SendAgentDataUpdate(remoteClient, dataForAgentID, activeGroupID, activeGroupName, activeGroupPowers, activeGroupTitle);
334 369
335 SendScenePresenceUpdate(dataForAgentID, activeGroupTitle); 370 SendAgentGroupDataUpdate(remoteClient, false);
371 // its a info request not a change, so nothing is sent to others
372 // they do get the group title with the avatar object update on arrivel to a region
336 } 373 }
337 374
338 private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient) 375 private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient)
@@ -403,7 +440,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
403 440
404 OutgoingInstantMessage(msg, inviteInfo.AgentID); 441 OutgoingInstantMessage(msg, inviteInfo.AgentID);
405 442
406 UpdateAllClientsWithGroupInfo(inviteInfo.AgentID); 443 IClientAPI client = GetActiveClient(inviteInfo.AgentID);
444 if (client != null)
445 SendDataUpdate(remoteClient, true);
407 446
408 // TODO: If the inviter is still online, they need an agent dataupdate 447 // TODO: If the inviter is still online, they need an agent dataupdate
409 // and maybe group membership updates for the invitee 448 // and maybe group membership updates for the invitee
@@ -656,13 +695,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
656 { 695 {
657 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 696 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
658 697
659 m_groupData.SetAgentActiveGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); 698 UUID agentID = GetRequestingAgentID(remoteClient);
699 m_groupData.SetAgentActiveGroup(agentID, agentID, groupID);
660 700
661 // Changing active group changes title, active powers, all kinds of things 701 // llClientView does this
662 // anyone who is in any region that can see this client, should probably be 702 SendAgentGroupDataUpdate(remoteClient, true);
663 // updated with new group info. At a minimum, they should get ScenePresence
664 // updated with new title.
665 UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient));
666 } 703 }
667 704
668 /// <summary> 705 /// <summary>
@@ -672,7 +709,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
672 { 709 {
673 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 710 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
674 711
675
676 List<GroupRolesData> agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); 712 List<GroupRolesData> agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID);
677 GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); 713 GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID);
678 714
@@ -710,7 +746,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
710 } 746 }
711 747
712 return data; 748 return data;
713
714 } 749 }
715 750
716 public List<GroupRolesData> GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID) 751 public List<GroupRolesData> GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID)
@@ -848,7 +883,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
848 remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); 883 remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly");
849 884
850 // Update the founder with new group information. 885 // Update the founder with new group information.
851 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 886 SendAgentGroupDataUpdate(remoteClient, false);
852 887
853 return groupID; 888 return groupID;
854 } 889 }
@@ -889,10 +924,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
889 // TODO: Not sure what all is needed here, but if the active group role change is for the group 924 // TODO: Not sure what all is needed here, but if the active group role change is for the group
890 // the client currently has set active, then we need to do a scene presence update too 925 // the client currently has set active, then we need to do a scene presence update too
891 // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) 926 // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID)
892
893 UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient));
894 }
895 927
928 SendDataUpdate(remoteClient, true);
929 }
896 930
897 public void GroupRoleUpdate(IClientAPI remoteClient, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, byte updateType) 931 public void GroupRoleUpdate(IClientAPI remoteClient, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, byte updateType)
898 { 932 {
@@ -929,7 +963,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
929 } 963 }
930 964
931 // TODO: This update really should send out updates for everyone in the role that just got changed. 965 // TODO: This update really should send out updates for everyone in the role that just got changed.
932 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 966 SendAgentGroupDataUpdate(remoteClient, false);
933 } 967 }
934 968
935 public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) 969 public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes)
@@ -955,7 +989,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
955 } 989 }
956 990
957 // TODO: This update really should send out updates for everyone in the role that just got changed. 991 // TODO: This update really should send out updates for everyone in the role that just got changed.
958 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 992 SendAgentGroupDataUpdate(remoteClient, false);
959 } 993 }
960 994
961 public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) 995 public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID)
@@ -983,7 +1017,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
983 msg.toAgentID = agentID.Guid; 1017 msg.toAgentID = agentID.Guid;
984 msg.dialog = dialog; 1018 msg.dialog = dialog;
985 msg.fromGroup = true; 1019 msg.fromGroup = true;
986 msg.offline = (byte)0; 1020 msg.offline = (byte)1; // Allow this message to be stored for offline use
987 msg.ParentEstateID = 0; 1021 msg.ParentEstateID = 0;
988 msg.Position = Vector3.Zero; 1022 msg.Position = Vector3.Zero;
989 msg.RegionID = UUID.Zero.Guid; 1023 msg.RegionID = UUID.Zero.Guid;
@@ -1035,14 +1069,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1035 return msg; 1069 return msg;
1036 } 1070 }
1037 1071
1038 public void SendAgentGroupDataUpdate(IClientAPI remoteClient)
1039 {
1040 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1041
1042 // Send agent information about his groups
1043 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
1044 }
1045
1046 public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) 1072 public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID)
1047 { 1073 {
1048 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 1074 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -1052,8 +1078,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1052 1078
1053 remoteClient.SendJoinGroupReply(groupID, true); 1079 remoteClient.SendJoinGroupReply(groupID, true);
1054 1080
1055 // Should this send updates to everyone in the group? 1081 SendAgentGroupDataUpdate(remoteClient, true);
1056 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient));
1057 } 1082 }
1058 1083
1059 public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID) 1084 public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID)
@@ -1068,7 +1093,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1068 1093
1069 // SL sends out notifcations to the group messaging session that the person has left 1094 // SL sends out notifcations to the group messaging session that the person has left
1070 // Should this also update everyone who is in the group? 1095 // Should this also update everyone who is in the group?
1071 SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); 1096 SendAgentGroupDataUpdate(remoteClient, true);
1072 } 1097 }
1073 1098
1074 public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) 1099 public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID)
@@ -1177,10 +1202,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1177 msg.binaryBucket = new byte[0]; 1202 msg.binaryBucket = new byte[0];
1178 OutgoingInstantMessage(msg, agentID); 1203 OutgoingInstantMessage(msg, agentID);
1179 1204
1180
1181 // SL sends out messages to everyone in the group 1205 // SL sends out messages to everyone in the group
1182 // Who all should receive updates and what should they be updated with? 1206 // Who all should receive updates and what should they be updated with?
1183 UpdateAllClientsWithGroupInfo(ejecteeID); 1207 // just tell this the group change
1208 SendAgentGroupDataUpdate(remoteClient, false);
1209 // TODO fix the rest of sends
1184 } 1210 }
1185 1211
1186 public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID) 1212 public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID)
@@ -1303,67 +1329,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1303 return child; 1329 return child;
1304 } 1330 }
1305 1331
1306 /// <summary>
1307 /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'.
1308 /// </summary>
1309 private void SendGroupMembershipInfoViaCaps(IClientAPI remoteClient, UUID dataForAgentID, GroupMembershipData[] data)
1310 {
1311 if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1312
1313 OSDArray AgentData = new OSDArray(1);
1314 OSDMap AgentDataMap = new OSDMap(1);
1315 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID));
1316 AgentData.Add(AgentDataMap);
1317
1318 OSDArray GroupData = new OSDArray(data.Length);
1319 OSDArray NewGroupData = new OSDArray(data.Length);
1320
1321 foreach (GroupMembershipData membership in data)
1322 {
1323 if (GetRequestingAgentID(remoteClient) != dataForAgentID)
1324 {
1325 if (!membership.ListInProfile)
1326 {
1327 // If we're sending group info to remoteclient about another agent,
1328 // filter out groups the other agent doesn't want to share.
1329 continue;
1330 }
1331 }
1332
1333 OSDMap GroupDataMap = new OSDMap(6);
1334 OSDMap NewGroupDataMap = new OSDMap(1);
1335
1336 GroupDataMap.Add("GroupID", OSD.FromUUID(membership.GroupID));
1337 GroupDataMap.Add("GroupPowers", OSD.FromULong(membership.GroupPowers));
1338 GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(membership.AcceptNotices));
1339 GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(membership.GroupPicture));
1340 GroupDataMap.Add("Contribution", OSD.FromInteger(membership.Contribution));
1341 GroupDataMap.Add("GroupName", OSD.FromString(membership.GroupName));
1342 NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(membership.ListInProfile));
1343
1344 GroupData.Add(GroupDataMap);
1345 NewGroupData.Add(NewGroupDataMap);
1346 }
1347
1348 OSDMap llDataStruct = new OSDMap(3);
1349 llDataStruct.Add("AgentData", AgentData);
1350 llDataStruct.Add("GroupData", GroupData);
1351 llDataStruct.Add("NewGroupData", NewGroupData);
1352
1353 if (m_debugEnabled)
1354 {
1355 m_log.InfoFormat("[GROUPS]: {0}", OSDParser.SerializeJsonString(llDataStruct));
1356 }
1357
1358 IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>();
1359
1360 if (queue != null)
1361 {
1362 queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient));
1363 }
1364
1365 }
1366
1367 private void SendScenePresenceUpdate(UUID AgentID, string Title) 1332 private void SendScenePresenceUpdate(UUID AgentID, string Title)
1368 { 1333 {
1369 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Updating scene title for {0} with title: {1}", AgentID, Title); 1334 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Updating scene title for {0} with title: {1}", AgentID, Title);
@@ -1380,54 +1345,35 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1380 presence.Grouptitle = Title; 1345 presence.Grouptitle = Title;
1381 1346
1382 if (! presence.IsChildAgent) 1347 if (! presence.IsChildAgent)
1383 presence.SendAvatarDataToAllClients(); 1348 presence.SendAvatarDataToAllAgents();
1384 } 1349 }
1385 } 1350 }
1386 } 1351 }
1387 } 1352 }
1388 1353
1389 /// <summary> 1354 public void SendAgentGroupDataUpdate(IClientAPI remoteClient)
1390 /// Send updates to all clients who might be interested in groups data for dataForClientID
1391 /// </summary>
1392 private void UpdateAllClientsWithGroupInfo(UUID dataForClientID)
1393 { 1355 {
1394 if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 1356 SendAgentGroupDataUpdate(remoteClient, true);
1395
1396 // TODO: Probably isn't nessesary to update every client in every scene.
1397 // Need to examine client updates and do only what's nessesary.
1398 lock (m_sceneList)
1399 {
1400 foreach (Scene scene in m_sceneList)
1401 {
1402 scene.ForEachClient(delegate(IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); });
1403 }
1404 }
1405 } 1357 }
1406 1358
1407 /// <summary> 1359 /// <summary>
1408 /// Update remoteClient with group information about dataForAgentID 1360 /// Tell remoteClient about its agent groups, and optionally send title to others
1409 /// </summary> 1361 /// </summary>
1410 private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForAgentID) 1362 private void SendAgentGroupDataUpdate(IClientAPI remoteClient, bool tellOthers)
1411 { 1363 {
1412 if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); 1364 if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name);
1413 1365
1414 // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff 1366 // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff
1415 1367
1416 OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero); 1368 UUID agentID = GetRequestingAgentID(remoteClient);
1417 1369
1418 // Need to send a group membership update to the client 1370 SendDataUpdate(remoteClient, tellOthers);
1419 // UDP version doesn't seem to behave nicely. But we're going to send it out here
1420 // with an empty group membership to hopefully remove groups being displayed due
1421 // to the core Groups Stub
1422 remoteClient.SendGroupMembership(new GroupMembershipData[0]);
1423 1371
1424 GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID); 1372 GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID);
1425 SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); 1373 remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray);
1426 remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray);
1427 1374
1428 if (remoteClient.AgentId == dataForAgentID) 1375 remoteClient.RefreshGroupMembership();
1429 remoteClient.RefreshGroupMembership(); 1376 }
1430 }
1431 1377
1432 /// <summary> 1378 /// <summary>
1433 /// Get a list of groups memberships for the agent that are marked "ListInProfile" 1379 /// Get a list of groups memberships for the agent that are marked "ListInProfile"
@@ -1478,13 +1424,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1478 return membershipArray; 1424 return membershipArray;
1479 } 1425 }
1480 1426
1481 1427 //tell remoteClient about its agent group info, and optionally send title to others
1482 private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) 1428 private void SendDataUpdate(IClientAPI remoteClient, bool tellOthers)
1483 { 1429 {
1484 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 1430 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
1485 1431
1486 // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff 1432 UUID activeGroupID = UUID.Zero;
1487 UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID); 1433 string activeGroupTitle = string.Empty;
1434 string activeGroupName = string.Empty;
1435 ulong activeGroupPowers = (ulong)GroupPowers.None;
1436
1437 UUID agentID = GetRequestingAgentID(remoteClient);
1438 GroupMembershipData membership = m_groupData.GetAgentActiveMembership(agentID, agentID);
1439 if (membership != null)
1440 {
1441 activeGroupID = membership.GroupID;
1442 activeGroupTitle = membership.GroupTitle;
1443 activeGroupPowers = membership.GroupPowers;
1444 activeGroupName = membership.GroupName;
1445 }
1446
1447 UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, agentID);
1488 string firstname, lastname; 1448 string firstname, lastname;
1489 if (account != null) 1449 if (account != null)
1490 { 1450 {
@@ -1497,9 +1457,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1497 lastname = "Unknown"; 1457 lastname = "Unknown";
1498 } 1458 }
1499 1459
1500 remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname, 1460 remoteClient.SendAgentDataUpdate(agentID, activeGroupID, firstname,
1501 lastname, activeGroupPowers, activeGroupName, 1461 lastname, activeGroupPowers, activeGroupName,
1502 activeGroupTitle); 1462 activeGroupTitle);
1463
1464 if (tellOthers)
1465 SendScenePresenceUpdate(agentID, activeGroupTitle);
1466
1467 ScenePresence sp = (ScenePresence)remoteClient.SceneAgent;
1468 if (sp != null)
1469 sp.Grouptitle = activeGroupTitle;
1503 } 1470 }
1504 1471
1505 #endregion 1472 #endregion
diff --git a/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs
index 0c3446d..4e766eb 100644
--- a/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs
+++ b/OpenSim/Region/OptionalModules/DataSnapshot/DataSnapshotManager.cs
@@ -432,7 +432,6 @@ namespace OpenSim.Region.DataSnapshot
432 m_log.Info("[DATASNAPSHOT]: data service " + url + " notified. Secret: " + m_Secret); 432 m_log.Info("[DATASNAPSHOT]: data service " + url + " notified. Secret: " + m_Secret);
433 } 433 }
434 } 434 }
435
436 } 435 }
437 #endregion 436 #endregion
438 437
diff --git a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
index 395bbf1..50a5fae 100644
--- a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
+++ b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs
@@ -135,30 +135,40 @@ namespace OpenSim.Region.OptionalModules
135 135
136 private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) 136 private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene)
137 { 137 {
138 if (newPoint.X < -1f || newPoint.X > (scene.RegionInfo.RegionSizeX + 1) ||
139 newPoint.Y < -1f || newPoint.Y > (scene.RegionInfo.RegionSizeY) )
140 return true;
141
138 SceneObjectPart obj = scene.GetSceneObjectPart(objectID); 142 SceneObjectPart obj = scene.GetSceneObjectPart(objectID);
139 Vector3 oldPoint = obj.GroupPosition; 143
140 int objectCount = obj.ParentGroup.PrimCount; 144 if (obj == null)
141 ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); 145 return false;
146
147 // Prim counts are determined by the location of the root prim. if we're
148 // moving a child prim, just let it pass
149 if (!obj.IsRoot)
150 {
151 return true;
152 }
153
142 ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); 154 ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y);
143 155
144 // newParcel will be null only if it outside of our current region. If this is the case, then the
145 // receiving permissions will perform the check.
146 if (newParcel == null) 156 if (newParcel == null)
147 return true; 157 return true;
148 158
149 // The prim hasn't crossed a region boundary so we don't need to worry 159 Vector3 oldPoint = obj.GroupPosition;
160 ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y);
161
162 // The prim hasn't crossed a region boundry so we don't need to worry
150 // about prim counts here 163 // about prim counts here
151 if(oldParcel.Equals(newParcel)) 164 if(oldParcel != null && oldParcel.Equals(newParcel))
152 { 165 {
153 return true; 166 return true;
154 } 167 }
155 168
156 // Prim counts are determined by the location of the root prim. if we're 169 int objectCount = obj.ParentGroup.PrimCount;
157 // moving a child prim, just let it pass 170 int usedPrims = newParcel.PrimCounts.Total;
158 if(!obj.IsRoot) 171 int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount();
159 {
160 return true;
161 }
162 172
163 // TODO: Add Special Case here for temporary prims 173 // TODO: Add Special Case here for temporary prims
164 174
diff --git a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
index 4bf2a82..e5e76e9 100644
--- a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
@@ -196,6 +196,7 @@ namespace OpenSim.Region.RegionCombinerModule
196 RootRegionLandChannel.SetParcelOtherCleanTime(remoteClient, localID, otherCleanTime); 196 RootRegionLandChannel.SetParcelOtherCleanTime(remoteClient, localID, otherCleanTime);
197 } 197 }
198 198
199 public void sendClientInitialLandInfo(IClientAPI remoteClient) { }
199 #endregion 200 #endregion
200 } 201 }
201} \ No newline at end of file 202} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerPermissionModule.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerPermissionModule.cs
index 07dd68b..ddfe3e0 100644
--- a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerPermissionModule.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionCombinerPermissionModule.cs
@@ -105,9 +105,9 @@ namespace OpenSim.Region.RegionCombinerModule
105 return m_rootScene.Permissions.CanEditObject(objectid, editorid); 105 return m_rootScene.Permissions.CanEditObject(objectid, editorid);
106 } 106 }
107 107
108 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers g, Scene scene) 108 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers g, Scene scene, bool allowManager)
109 { 109 {
110 return m_rootScene.Permissions.CanEditParcelProperties(user, parcel, g); 110 return m_rootScene.Permissions.CanEditParcelProperties(user, parcel, g, allowManager);
111 } 111 }
112 112
113 public bool CanInstantMessage(UUID user, UUID target, Scene startscene) 113 public bool CanInstantMessage(UUID user, UUID target, Scene startscene)
diff --git a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionConnections.cs b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionConnections.cs
index 62a3a91..6bf1c4a 100644
--- a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionConnections.cs
+++ b/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionConnections.cs
@@ -91,4 +91,4 @@ namespace OpenSim.Region.RegionCombinerModule
91 YEnd = (uint)extents.Y; 91 YEnd = (uint)extents.Y;
92 } 92 }
93 } 93 }
94} \ No newline at end of file 94}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index edf51a2..e7d461f 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -746,8 +746,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
746 746
747 List<SceneObjectGroup> objlist; 747 List<SceneObjectGroup> objlist;
748 List<Vector3> veclist; 748 List<Vector3> veclist;
749 749
750 bool success = host.RootPart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist); 750 Vector3 bbox = new Vector3();
751 float offsetHeight;
752 bool success = host.RootPart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist, out bbox, out offsetHeight);
751 if (! success) 753 if (! success)
752 { 754 {
753 GenerateRuntimeError("Failed to create object"); 755 GenerateRuntimeError("Failed to create object");
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
index 744d1e3..4b7295d 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
@@ -178,7 +178,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
178 { 178 {
179 if(!m_Channels.ContainsKey(itemID)) 179 if(!m_Channels.ContainsKey(itemID))
180 { 180 {
181 m_log.InfoFormat("[XMLRPC GRID ROUTER]: Attempted to unregister non-existing Item: {0}", itemID.ToString()); 181 //m_log.InfoFormat("[XMLRPC GRID ROUTER]: Attempted to unregister non-existing Item: {0}", itemID.ToString());
182 return false; 182 return false;
183 } 183 }
184 184
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
index 943675e..32549d6 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
@@ -98,7 +98,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
98 98
99 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) 99 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri)
100 { 100 {
101 scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] {uri}); 101 if (m_Enabled)
102 {
103 scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] { uri });
104 }
102 } 105 }
103 106
104 public void UnRegisterReceiver(string channelID, UUID itemID) 107 public void UnRegisterReceiver(string channelID, UUID itemID)
diff --git a/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs b/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs
index bcb6361..bd5289f 100644
--- a/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/OptionalModules/UserStatistics/WebStatsModule.cs
@@ -1197,7 +1197,7 @@ VALUES
1197 m_pendingDownloads = stats.StatsBlock[17].StatValue; 1197 m_pendingDownloads = stats.StatsBlock[17].StatValue;
1198 m_pendingUploads = stats.StatsBlock[18].StatValue; 1198 m_pendingUploads = stats.StatsBlock[18].StatValue;
1199 m_activeScripts = stats.StatsBlock[19].StatValue; 1199 m_activeScripts = stats.StatsBlock[19].StatValue;
1200 m_scriptLinesPerSecond = stats.StatsBlock[20].StatValue; 1200 m_scriptLinesPerSecond = stats.ExtraStatsBlock[0].StatValue;
1201 } 1201 }
1202 } 1202 }
1203} \ No newline at end of file 1203} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
index d37369c..709a16d 100644
--- a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
@@ -131,8 +131,11 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport
131 { 131 {
132 foreach (MenuItemData d in m_menuItems[UUID.Zero]) 132 foreach (MenuItemData d in m_menuItems[UUID.Zero])
133 { 133 {
134 if (d.Mode == UserMode.God && (!m_scene.Permissions.IsGod(agentID))) 134 if (!m_scene.Permissions.IsGod(agentID))
135 continue; 135 {
136 if (d.Mode == UserMode.RegionManager && (!m_scene.Permissions.IsAdministrator(agentID)))
137 continue;
138 }
136 139
137 OSDMap loc = null; 140 OSDMap loc = null;
138 switch (d.Location) 141 switch (d.Location)
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index 4cd5676..8565f5a 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -205,8 +205,9 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
205 { 205 {
206 } 206 }
207 207
208 public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount) 208 public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount, UUID txn, out string result)
209 { 209 {
210 result = String.Empty;
210 string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID)); 211 string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID));
211 212
212 bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description); 213 bool give_result = doMoneyTransfer(fromID, toID, amount, 2, description);
@@ -842,6 +843,10 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
842 if (module != null) 843 if (module != null)
843 module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice); 844 module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice);
844 } 845 }
846
847 public void MoveMoney(UUID fromAgentID, UUID toAgentID, int amount, string text)
848 {
849 }
845 } 850 }
846 851
847 public enum TransactionType : int 852 public enum TransactionType : int
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index fb644b7..7228348 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -61,10 +61,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
61 private readonly string m_firstname; 61 private readonly string m_firstname;
62 private readonly string m_lastname; 62 private readonly string m_lastname;
63 private readonly Vector3 m_startPos; 63 private readonly Vector3 m_startPos;
64 private readonly UUID m_uuid; 64 private UUID m_uuid = UUID.Random();
65 private readonly Scene m_scene; 65 private readonly Scene m_scene;
66 private readonly UUID m_ownerID; 66 private readonly UUID m_ownerID;
67 67
68 public List<uint> SelectedObjects {get; private set;}
69
68 public NPCAvatar( 70 public NPCAvatar(
69 string firstname, string lastname, Vector3 position, UUID ownerID, bool senseAsAgent, Scene scene) 71 string firstname, string lastname, Vector3 position, UUID ownerID, bool senseAsAgent, Scene scene)
70 { 72 {
@@ -94,6 +96,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
94 get { return m_scene; } 96 get { return m_scene; }
95 } 97 }
96 98
99 public int PingTimeMS { get { return 0; } }
100
97 public UUID OwnerID 101 public UUID OwnerID
98 { 102 {
99 get { return m_ownerID; } 103 get { return m_ownerID; }
@@ -187,9 +191,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
187 { 191 {
188 192
189 } 193 }
190 194
191 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, 195 public void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY)
192 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) 196 {
197
198 }
199
200 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos,
201 Quaternion SitOrientation, bool autopilot,
202 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
193 { 203 {
194 204
195 } 205 }
@@ -248,7 +258,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
248#pragma warning disable 67 258#pragma warning disable 67
249 public event Action<IClientAPI> OnLogout; 259 public event Action<IClientAPI> OnLogout;
250 public event ObjectPermissions OnObjectPermissions; 260 public event ObjectPermissions OnObjectPermissions;
251 261 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
252 public event MoneyTransferRequest OnMoneyTransferRequest; 262 public event MoneyTransferRequest OnMoneyTransferRequest;
253 public event ParcelBuy OnParcelBuy; 263 public event ParcelBuy OnParcelBuy;
254 public event Action<IClientAPI> OnConnectionClosed; 264 public event Action<IClientAPI> OnConnectionClosed;
@@ -268,6 +278,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
268 public event ObjectDrop OnObjectDrop; 278 public event ObjectDrop OnObjectDrop;
269 public event StartAnim OnStartAnim; 279 public event StartAnim OnStartAnim;
270 public event StopAnim OnStopAnim; 280 public event StopAnim OnStopAnim;
281 public event ChangeAnim OnChangeAnim;
271 public event LinkObjects OnLinkObjects; 282 public event LinkObjects OnLinkObjects;
272 public event DelinkObjects OnDelinkObjects; 283 public event DelinkObjects OnDelinkObjects;
273 public event RequestMapBlocks OnRequestMapBlocks; 284 public event RequestMapBlocks OnRequestMapBlocks;
@@ -318,6 +329,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
318 public event UpdatePrimTexture OnUpdatePrimTexture; 329 public event UpdatePrimTexture OnUpdatePrimTexture;
319 public event UpdateVector OnUpdatePrimGroupPosition; 330 public event UpdateVector OnUpdatePrimGroupPosition;
320 public event UpdateVector OnUpdatePrimSinglePosition; 331 public event UpdateVector OnUpdatePrimSinglePosition;
332 public event ClientChangeObject onClientChangeObject;
321 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 333 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
322 public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition; 334 public event UpdatePrimSingleRotationPosition OnUpdatePrimSingleRotationPosition;
323 public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation; 335 public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
@@ -456,7 +468,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
456 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 468 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
457 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 469 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
458 public event ClassifiedDelete OnClassifiedDelete; 470 public event ClassifiedDelete OnClassifiedDelete;
459 public event ClassifiedDelete OnClassifiedGodDelete; 471 public event ClassifiedGodDelete OnClassifiedGodDelete;
460 472
461 public event EventNotificationAddRequest OnEventNotificationAddRequest; 473 public event EventNotificationAddRequest OnEventNotificationAddRequest;
462 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 474 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -495,11 +507,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
495 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 507 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
496 public event SimWideDeletesDelegate OnSimWideDeletes; 508 public event SimWideDeletesDelegate OnSimWideDeletes;
497 public event SendPostcard OnSendPostcard; 509 public event SendPostcard OnSendPostcard;
510 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
498 public event MuteListEntryUpdate OnUpdateMuteListEntry; 511 public event MuteListEntryUpdate OnUpdateMuteListEntry;
499 public event MuteListEntryRemove OnRemoveMuteListEntry; 512 public event MuteListEntryRemove OnRemoveMuteListEntry;
500 public event GodlikeMessage onGodlikeMessage; 513 public event GodlikeMessage onGodlikeMessage;
501 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 514 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
502 515 public event GenericCall2 OnUpdateThrottles;
503#pragma warning restore 67 516#pragma warning restore 67
504 517
505 #endregion 518 #endregion
@@ -522,6 +535,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
522 public virtual UUID AgentId 535 public virtual UUID AgentId
523 { 536 {
524 get { return m_uuid; } 537 get { return m_uuid; }
538 set { m_uuid = value; }
525 } 539 }
526 540
527 public UUID SessionId 541 public UUID SessionId
@@ -627,6 +641,17 @@ namespace OpenSim.Region.OptionalModules.World.NPC
627 public virtual void SetChildAgentThrottle(byte[] throttle) 641 public virtual void SetChildAgentThrottle(byte[] throttle)
628 { 642 {
629 } 643 }
644
645 public virtual void SetChildAgentThrottle(byte[] throttle, float factor)
646 {
647
648 }
649
650 public void SetAgentThrottleSilent(int throttle, int setting)
651 {
652
653
654 }
630 public byte[] GetThrottlesPacked(float multiplier) 655 public byte[] GetThrottlesPacked(float multiplier)
631 { 656 {
632 return new byte[0]; 657 return new byte[0];
@@ -665,6 +690,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
665 690
666 } 691 }
667 692
693 public virtual bool CanSendLayerData()
694 {
695 return false;
696 }
697
668 public virtual void SendLayerData(float[] map) 698 public virtual void SendLayerData(float[] map)
669 { 699 {
670 } 700 }
@@ -772,6 +802,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
772 { 802 {
773 } 803 }
774 804
805 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
806 {
807 }
808
775 public virtual void SendRemoveInventoryItem(UUID itemID) 809 public virtual void SendRemoveInventoryItem(UUID itemID)
776 { 810 {
777 } 811 }
@@ -788,7 +822,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
788 { 822 {
789 } 823 }
790 824
791 public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data) 825 public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
792 { 826 {
793 } 827 }
794 public virtual void SendAbortXferPacket(ulong xferID) 828 public virtual void SendAbortXferPacket(ulong xferID)
@@ -933,10 +967,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
933 967
934 public void Close() 968 public void Close()
935 { 969 {
936 Close(false); 970 Close(true, false);
937 } 971 }
938 972
939 public void Close(bool force) 973 public void Close(bool sendStop, bool force)
940 { 974 {
941 // Remove ourselves from the scene 975 // Remove ourselves from the scene
942 m_scene.RemoveClient(AgentId, false); 976 m_scene.RemoveClient(AgentId, false);
@@ -1155,6 +1189,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
1155 { 1189 {
1156 } 1190 }
1157 1191
1192 public void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data)
1193 {
1194 }
1195
1158 public void SendTerminateFriend(UUID exFriendID) 1196 public void SendTerminateFriend(UUID exFriendID)
1159 { 1197 {
1160 } 1198 }
@@ -1269,5 +1307,14 @@ namespace OpenSim.Region.OptionalModules.World.NPC
1269 { 1307 {
1270 } 1308 }
1271 1309
1310 public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
1311 {
1312 }
1313
1314 public int GetAgentThrottleSilent(int throttle)
1315 {
1316 return 0;
1317 }
1318
1272 } 1319 }
1273} 1320}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 9232db9..d40fa48 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -52,6 +52,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
52 private Dictionary<UUID, NPCAvatar> m_avatars = 52 private Dictionary<UUID, NPCAvatar> m_avatars =
53 new Dictionary<UUID, NPCAvatar>(); 53 new Dictionary<UUID, NPCAvatar>();
54 54
55
56
57 private NPCOptionsFlags m_NPCOptionFlags;
58 public NPCOptionsFlags NPCOptionFlags {get {return m_NPCOptionFlags;}}
59
55 public bool Enabled { get; private set; } 60 public bool Enabled { get; private set; }
56 61
57 public void Initialise(IConfigSource source) 62 public void Initialise(IConfigSource source)
@@ -59,6 +64,21 @@ namespace OpenSim.Region.OptionalModules.World.NPC
59 IConfig config = source.Configs["NPC"]; 64 IConfig config = source.Configs["NPC"];
60 65
61 Enabled = (config != null && config.GetBoolean("Enabled", false)); 66 Enabled = (config != null && config.GetBoolean("Enabled", false));
67 m_NPCOptionFlags = NPCOptionsFlags.None;
68 if(Enabled)
69 {
70 if(config.GetBoolean("AllowNotOwned", true))
71 m_NPCOptionFlags |= NPCOptionsFlags.AllowNotOwned;
72
73 if(config.GetBoolean("AllowSenseAsAvatar", true))
74 m_NPCOptionFlags |= NPCOptionsFlags.AllowSenseAsAvatar;
75
76 if(config.GetBoolean("AllowCloneOtherAvatars", true))
77 m_NPCOptionFlags |= NPCOptionsFlags.AllowCloneOtherAvatars;
78
79 if(config.GetBoolean("NoNPCGroup", true))
80 m_NPCOptionFlags |= NPCOptionsFlags.NoNPCGroup;
81 }
62 } 82 }
63 83
64 public void AddRegion(Scene scene) 84 public void AddRegion(Scene scene)
@@ -167,10 +187,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
167 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, 187 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0,
168 int.MaxValue); 188 int.MaxValue);
169 189
170 m_log.DebugFormat( 190// m_log.DebugFormat(
171 "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}", 191// "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
172 firstname, lastname, npcAvatar.AgentId, owner, 192// firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName);
173 senseAsAgent, position, scene.RegionInfo.RegionName);
174 193
175 AgentCircuitData acd = new AgentCircuitData(); 194 AgentCircuitData acd = new AgentCircuitData();
176 acd.AgentID = npcAvatar.AgentId; 195 acd.AgentID = npcAvatar.AgentId;
@@ -192,36 +211,31 @@ namespace OpenSim.Region.OptionalModules.World.NPC
192 } 211 }
193 */ 212 */
194 213
195 lock (m_avatars) 214// ManualResetEvent ev = new ManualResetEvent(false);
196 {
197 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode,
198 acd);
199 scene.AddNewAgent(npcAvatar, PresenceType.Npc);
200 215
201 ScenePresence sp; 216// Util.FireAndForget(delegate(object x) {
202 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) 217 lock (m_avatars)
203 { 218 {
204 /* 219 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
205 m_log.DebugFormat( 220 scene.AddNewAgent(npcAvatar, PresenceType.Npc);
206 "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}",
207 sp.Name, sp.UUID);
208 */
209
210 sp.CompleteMovement(npcAvatar, false);
211 m_avatars.Add(npcAvatar.AgentId, npcAvatar);
212 m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
213 221
214 return npcAvatar.AgentId; 222 ScenePresence sp;
223 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
224 {
225
226 sp.CompleteMovement(npcAvatar, false);
227 m_avatars.Add(npcAvatar.AgentId, npcAvatar);
228// m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
229 }
215 } 230 }
216 else 231// ev.Set();
217 { 232// });
218 m_log.WarnFormat(
219 "[NPC MODULE]: Could not find scene presence for NPC {0} {1}",
220 sp.Name, sp.UUID);
221 233
222 return UUID.Zero; 234// ev.WaitOne();
223 } 235
224 } 236// m_log.DebugFormat("[NPC MODULE]: Created NPC with id {0}", npcAvatar.AgentId);
237
238 return npcAvatar.AgentId;
225 } 239 }
226 240
227 public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, 241 public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos,
@@ -436,9 +450,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
436 { 450 {
437 NPCAvatar av; 451 NPCAvatar av;
438 if (m_avatars.TryGetValue(npcID, out av)) 452 if (m_avatars.TryGetValue(npcID, out av))
453 {
454 if (npcID == callerID)
455 return true;
439 return CheckPermissions(av, callerID); 456 return CheckPermissions(av, callerID);
457 }
440 else 458 else
459 {
441 return false; 460 return false;
461 }
442 } 462 }
443 } 463 }
444 464
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 77dfd40..a892cf4 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
112 // ScenePresence.SendInitialData() to reset our entire appearance. 112 // ScenePresence.SendInitialData() to reset our entire appearance.
113 m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); 113 m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId));
114 114
115 m_afMod.SetAppearance(sp, originalTe, null, null); 115 m_afMod.SetAppearance(sp, originalTe, null, new WearableCacheItem[0] );
116 116
117 UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance); 117 UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance);
118 118
@@ -483,4 +483,4 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
483 Assert.That(npc.ParentID, Is.EqualTo(0)); 483 Assert.That(npc.ParentID, Is.EqualTo(0));
484 } 484 }
485 } 485 }
486} \ No newline at end of file 486}
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index 0927c4f..1102aca 100644
--- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -166,7 +166,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
166 cdl.AddRow("physics", m_scene.PhysicsEnabled); 166 cdl.AddRow("physics", m_scene.PhysicsEnabled);
167 cdl.AddRow("scripting", m_scene.ScriptsEnabled); 167 cdl.AddRow("scripting", m_scene.ScriptsEnabled);
168 cdl.AddRow("teleport", m_scene.DebugTeleporting); 168 cdl.AddRow("teleport", m_scene.DebugTeleporting);
169 cdl.AddRow("update-on-timer", m_scene.UpdateOnTimer); 169// cdl.AddRow("update-on-timer", m_scene.UpdateOnTimer);
170 cdl.AddRow("updates", m_scene.DebugUpdates); 170 cdl.AddRow("updates", m_scene.DebugUpdates);
171 171
172 MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name); 172 MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name);
@@ -313,7 +313,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
313 bool enableUpdateOnTimer; 313 bool enableUpdateOnTimer;
314 if (bool.TryParse(options["update-on-timer"], out enableUpdateOnTimer)) 314 if (bool.TryParse(options["update-on-timer"], out enableUpdateOnTimer))
315 { 315 {
316 m_scene.UpdateOnTimer = enableUpdateOnTimer; 316// m_scene.UpdateOnTimer = enableUpdateOnTimer;
317 m_scene.Active = false; 317 m_scene.Active = false;
318 318
319 while (m_scene.IsRunning) 319 while (m_scene.IsRunning)
@@ -334,4 +334,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
334 } 334 }
335 } 335 }
336 } 336 }
337} \ No newline at end of file 337}
diff --git a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs
index e7b30ba..3944047 100644
--- a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs
+++ b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsActor.cs
@@ -211,7 +211,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
211 { 211 {
212 } 212 }
213 213
214 public override void LockAngularMotion(Vector3 axis) 214 public override void LockAngularMotion(byte axislocks)
215 { 215 {
216 } 216 }
217 217
@@ -254,6 +254,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
254 254
255 public override bool PIDHoverActive 255 public override bool PIDHoverActive
256 { 256 {
257 get { return false; }
257 set { return; } 258 set { return; }
258 } 259 }
259 260
diff --git a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs
index 5383f1b..d2cd028 100644
--- a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs
+++ b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsPrim.cs
@@ -224,7 +224,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
224 { 224 {
225 } 225 }
226 226
227 public override void LockAngularMotion(Vector3 axis) 227 public override void LockAngularMotion(byte axislocks)
228 { 228 {
229 } 229 }
230 230
@@ -267,6 +267,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
267 267
268 public override bool PIDHoverActive 268 public override bool PIDHoverActive
269 { 269 {
270 get { return false; }
270 set { return; } 271 set { return; }
271 } 272 }
272 273
diff --git a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs
index 20b337a..ac2c1f3 100644
--- a/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs
+++ b/OpenSim/Region/PhysicsModules/BasicPhysics/BasicPhysicsScene.cs
@@ -220,7 +220,7 @@ namespace OpenSim.Region.PhysicsModule.BasicPhysics
220 actor.Velocity = actorVelocity; 220 actor.Velocity = actorVelocity;
221 } 221 }
222 222
223 return fps; 223 return 1.0f;
224 } 224 }
225 225
226 public override void GetResults() 226 public override void GetResults()
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
index 83fc3a6..989b339 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSCharacter.cs
@@ -300,7 +300,7 @@ public sealed class BSCharacter : BSPhysObject
300 } 300 }
301 301
302 302
303 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 303 public override void LockAngularMotion(byte axislocks) { return; }
304 304
305 public override OMV.Vector3 Position { 305 public override OMV.Vector3 Position {
306 get { 306 get {
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs
index da3fc18..c3eb776 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSPhysObject.cs
@@ -268,7 +268,7 @@ public abstract class BSPhysObject : PhysicsActor
268 public float MoveToTargetTau { get; set; } 268 public float MoveToTargetTau { get; set; }
269 269
270 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z 270 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
271 public override bool PIDHoverActive { set { HoverActive = value; } } 271 public override bool PIDHoverActive {get {return HoverActive;} set { HoverActive = value; } }
272 public override float PIDHoverHeight { set { HoverHeight = value; } } 272 public override float PIDHoverHeight { set { HoverHeight = value; } }
273 public override PIDHoverType PIDHoverType { set { HoverType = value; } } 273 public override PIDHoverType PIDHoverType { set { HoverType = value; } }
274 public override float PIDHoverTau { set { HoverTau = value; } } 274 public override float PIDHoverTau { set { HoverTau = value; } }
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
index 6f27ac7..1d552eb 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSPrim.cs
@@ -33,7 +33,7 @@ using log4net;
33using OMV = OpenMetaverse; 33using OMV = OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.PhysicsModules.SharedBase; 35using OpenSim.Region.PhysicsModules.SharedBase;
36using OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet; 36using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet;
37 37
38namespace OpenSim.Region.PhysicsModule.BulletS 38namespace OpenSim.Region.PhysicsModule.BulletS
39{ 39{
@@ -280,20 +280,20 @@ public class BSPrim : BSPhysObject
280 }); 280 });
281 } 281 }
282 282
283 public override void LockAngularMotion(OMV.Vector3 axis) 283 public override void LockAngularMotion(byte axislocks)
284 { 284 {
285 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 285 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axislocks);
286 286
287 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR, 0f, 0f); 287 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_UNLOCK_ANGULAR, 0f, 0f);
288 if (axis.X != 1) 288 if ((axislocks & 0x02) != 0)
289 { 289 {
290 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_X, 0f, 0f); 290 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_X, 0f, 0f);
291 } 291 }
292 if (axis.Y != 1) 292 if ((axislocks & 0x04) != 0)
293 { 293 {
294 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Y, 0f, 0f); 294 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Y, 0f, 0f);
295 } 295 }
296 if (axis.Z != 1) 296 if ((axislocks & 0x08) != 0)
297 { 297 {
298 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Z, 0f, 0f); 298 ApplyAxisLimits(ExtendedPhysics.PHYS_AXIS_LOCK_ANGULAR_Z, 0f, 0f);
299 } 299 }
@@ -647,6 +647,59 @@ public class BSPrim : BSPhysObject
647 }); 647 });
648 } 648 }
649 649
650 public override void SetVehicle(object pvdata)
651 {
652 PhysScene.TaintedObject(LocalID, "BSPrim.SetVehicle", delegate ()
653 {
654 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
655 if (vehicleActor != null && (pvdata is VehicleData) )
656 {
657 VehicleData vdata = (VehicleData)pvdata;
658 // vehicleActor.ProcessSetVehicle((VehicleData)vdata);
659
660 vehicleActor.ProcessTypeChange(vdata.m_type);
661 vehicleActor.ProcessVehicleFlags(-1, false);
662 vehicleActor.ProcessVehicleFlags((int)vdata.m_flags, false);
663
664 // Linear properties
665 vehicleActor.ProcessVectorVehicleParam(Vehicle.LINEAR_MOTOR_DIRECTION, vdata.m_linearMotorDirection);
666 vehicleActor.ProcessVectorVehicleParam(Vehicle.LINEAR_FRICTION_TIMESCALE, vdata.m_linearFrictionTimescale);
667 vehicleActor.ProcessFloatVehicleParam(Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE, vdata.m_linearMotorDecayTimescale);
668 vehicleActor.ProcessFloatVehicleParam(Vehicle.LINEAR_MOTOR_TIMESCALE, vdata.m_linearMotorTimescale);
669 vehicleActor.ProcessVectorVehicleParam(Vehicle.LINEAR_MOTOR_OFFSET, vdata.m_linearMotorOffset);
670
671 //Angular properties
672 vehicleActor.ProcessVectorVehicleParam(Vehicle.ANGULAR_MOTOR_DIRECTION, vdata.m_angularMotorDirection);
673 vehicleActor.ProcessFloatVehicleParam(Vehicle.ANGULAR_MOTOR_TIMESCALE, vdata.m_angularMotorTimescale);
674 vehicleActor.ProcessFloatVehicleParam(Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE, vdata.m_angularMotorDecayTimescale);
675 vehicleActor.ProcessVectorVehicleParam(Vehicle.ANGULAR_FRICTION_TIMESCALE, vdata.m_angularFrictionTimescale);
676
677 //Deflection properties
678 vehicleActor.ProcessFloatVehicleParam(Vehicle.ANGULAR_DEFLECTION_EFFICIENCY, vdata.m_angularDeflectionEfficiency);
679 vehicleActor.ProcessFloatVehicleParam(Vehicle.ANGULAR_DEFLECTION_TIMESCALE, vdata.m_angularDeflectionTimescale);
680 vehicleActor.ProcessFloatVehicleParam(Vehicle.LINEAR_DEFLECTION_EFFICIENCY, vdata.m_linearDeflectionEfficiency);
681 vehicleActor.ProcessFloatVehicleParam(Vehicle.LINEAR_DEFLECTION_TIMESCALE, vdata.m_linearDeflectionTimescale);
682
683 //Banking properties
684 vehicleActor.ProcessFloatVehicleParam(Vehicle.BANKING_EFFICIENCY, vdata.m_bankingEfficiency);
685 vehicleActor.ProcessFloatVehicleParam(Vehicle.BANKING_MIX, vdata.m_bankingMix);
686 vehicleActor.ProcessFloatVehicleParam(Vehicle.BANKING_TIMESCALE, vdata.m_bankingTimescale);
687
688 //Hover and Buoyancy properties
689 vehicleActor.ProcessFloatVehicleParam(Vehicle.HOVER_HEIGHT, vdata.m_VhoverHeight);
690 vehicleActor.ProcessFloatVehicleParam(Vehicle.HOVER_EFFICIENCY, vdata.m_VhoverEfficiency);
691 vehicleActor.ProcessFloatVehicleParam(Vehicle.HOVER_TIMESCALE, vdata.m_VhoverTimescale);
692 vehicleActor.ProcessFloatVehicleParam(Vehicle.BUOYANCY, vdata.m_VehicleBuoyancy);
693
694 //Attractor properties
695 vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, vdata.m_verticalAttractionEfficiency);
696 vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, vdata.m_verticalAttractionTimescale);
697
698 vehicleActor.ProcessRotationVehicleParam(Vehicle.REFERENCE_FRAME, vdata.m_referenceFrame);
699 }
700 });
701 }
702
650 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 703 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
651 public override void SetVolumeDetect(int param) { 704 public override void SetVolumeDetect(int param) {
652 bool newValue = (param != 0); 705 bool newValue = (param != 0);
@@ -1173,6 +1226,10 @@ public class BSPrim : BSPhysObject
1173 // Used for llSetHoverHeight and maybe vehicle height 1226 // Used for llSetHoverHeight and maybe vehicle height
1174 // Hover Height will override MoveTo target's Z 1227 // Hover Height will override MoveTo target's Z
1175 public override bool PIDHoverActive { 1228 public override bool PIDHoverActive {
1229 get
1230 {
1231 return base.HoverActive;
1232 }
1176 set { 1233 set {
1177 base.HoverActive = value; 1234 base.HoverActive = value;
1178 EnableActor(HoverActive, HoverActorName, delegate() 1235 EnableActor(HoverActive, HoverActorName, delegate()
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
index 452ce55..b2d5e47 100644
--- a/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSScene.cs
@@ -762,7 +762,8 @@ namespace OpenSim.Region.PhysicsModule.BulletS
762 // The physics engine returns the number of milliseconds it simulated this call. 762 // The physics engine returns the number of milliseconds it simulated this call.
763 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 763 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
764 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). 764 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
765 m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; 765// m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
766 m_simulatedTime += (float)numSubSteps * m_fixedTimeStep;
766 } 767 }
767 768
768 // Called by a BSPhysObject to note that it has changed properties and this information 769 // Called by a BSPhysObject to note that it has changed properties and this information
@@ -849,7 +850,7 @@ namespace OpenSim.Region.PhysicsModule.BulletS
849 850
850 // Return the framerate simulated to give the above returned results. 851 // Return the framerate simulated to give the above returned results.
851 // (Race condition here but this is just bookkeeping so rare mistakes do not merit a lock). 852 // (Race condition here but this is just bookkeeping so rare mistakes do not merit a lock).
852 float simTime = m_simulatedTime; 853 float simTime = m_simulatedTime / timeStep;
853 m_simulatedTime = 0f; 854 m_simulatedTime = 0f;
854 return simTime; 855 return simTime;
855 } 856 }
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs b/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
index b100273..4ec6f51 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSShapeCollection.cs
@@ -30,7 +30,6 @@ using System.Text;
30using OMV = OpenMetaverse; 30using OMV = OpenMetaverse;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Region.PhysicsModules.SharedBase; 32using OpenSim.Region.PhysicsModules.SharedBase;
33using OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet;
34 33
35namespace OpenSim.Region.PhysicsModule.BulletS 34namespace OpenSim.Region.PhysicsModule.BulletS
36{ 35{
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSShapes.cs b/OpenSim/Region/PhysicsModules/BulletS/BSShapes.cs
index 086a412..e791b27 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/BSShapes.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/BSShapes.cs
@@ -31,8 +31,8 @@ using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.PhysicsModules.SharedBase; 33using OpenSim.Region.PhysicsModules.SharedBase;
34using OpenSim.Region.PhysicsModules.Meshing; 34using OpenSim.Region.PhysicsModule.Meshing;
35using OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet; 35using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet;
36 36
37using OMV = OpenMetaverse; 37using OMV = OpenMetaverse;
38 38
@@ -555,7 +555,9 @@ public class BSShapeMesh : BSShape
555 { 555 {
556 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, 556 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
557 false, // say it is not physical so a bounding box is not built 557 false, // say it is not physical so a bounding box is not built
558 false // do not cache the mesh and do not use previously built versions 558 false, // do not cache the mesh and do not use previously built versions
559 false,
560 false
559 ); 561 );
560 } 562 }
561 563
@@ -712,7 +714,7 @@ public class BSShapeHull : BSShape
712 lock (physicsScene.mesher) 714 lock (physicsScene.mesher)
713 { 715 {
714 // Pass true for physicalness as this prevents the creation of bounding box which is not needed 716 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
715 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */); 717 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
716 718
717 // If we should use the asset's hull info, fetch it out of the locked mesher 719 // If we should use the asset's hull info, fetch it out of the locked mesher
718 if (meshData != null && BSParam.ShouldUseAssetHulls) 720 if (meshData != null && BSParam.ShouldUseAssetHulls)
diff --git a/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs b/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs
index 4eeea4d..109e19c 100755
--- a/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs
+++ b/OpenSim/Region/PhysicsModules/BulletS/Tests/BulletSimTestsUtil.cs
@@ -34,7 +34,7 @@ using Nini.Config;
34 34
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.PhysicsModules.SharedBase; 36using OpenSim.Region.PhysicsModules.SharedBase;
37using OpenSim.Region.PhysicsModules.Meshing; 37using OpenSim.Region.PhysicsModule.Meshing;
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39 39
40using OpenMetaverse; 40using OpenMetaverse;
@@ -86,7 +86,7 @@ public static class BulletSimTestsUtil
86 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize; 86 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize;
87 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info); 87 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info);
88 88
89 IMesher mesher = new OpenSim.Region.PhysicsModules.Meshing.Meshmerizer(); 89 IMesher mesher = new OpenSim.Region.PhysicsModule.Meshing.Meshmerizer();
90 INonSharedRegionModule mod = mesher as INonSharedRegionModule; 90 INonSharedRegionModule mod = mesher as INonSharedRegionModule;
91 mod.Initialise(openSimINI); 91 mod.Initialise(openSimINI);
92 mod.AddRegion(scene); 92 mod.AddRegion(scene);
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs
index 7ad689e..3d81439 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/CTri.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class Wpoint 33 public class Wpoint
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs
index 4140d25..6a98535 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Concavity.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public static class Concavity 34 public static class Concavity
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs
index 70c3a2b..4480036 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexBuilder.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public class DecompDesc 34 public class DecompDesc
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs
index 5046bce..e6dc98a 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexDecomposition.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public delegate void ConvexDecompositionCallback(ConvexResult result); 34 public delegate void ConvexDecompositionCallback(ConvexResult result);
35 35
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs
index 44e3e50..09129ed 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/ConvexResult.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class ConvexResult 33 public class ConvexResult
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs
index 8a0164e..7d342d1 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullClasses.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class HullResult 33 public class HullResult
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs
index d3f0052..66457ac 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullTriangle.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public class HullTriangle : int3 34 public class HullTriangle : int3
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs
index 3903254..b0bbfb9 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/HullUtils.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public static class HullUtils 34 public static class HullUtils
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs
index da9ae0c..f58cad6 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Plane.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class Plane 32 public class Plane
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs
index 42f7a22..8f08ddf 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/PlaneTri.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public enum PlaneTriResult : int 34 public enum PlaneTriResult : int
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs
index 045f620..2d72117 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/Quaternion.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class Quaternion : float4 32 public class Quaternion : float4
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs
index 9f56bc5..cc5f99c 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/SplitPlane.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class Rect3d 33 public class Rect3d
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs
index bfe11e5..da2255e 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/VertexLookup.cs
@@ -28,7 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 31namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
32{ 32{
33 public class VertexPool 33 public class VertexPool
34 { 34 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs
index e7358c1..2a58ec4 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float2.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class float2 32 public class float2
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs
index fde9b32..64a9ef8 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class float3 : IEquatable<float3> 32 public class float3 : IEquatable<float3>
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs
index c420fde..266ed0b 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float3x3.cs
@@ -29,7 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; 30using System.Diagnostics;
31 31
32namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 32namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
33{ 33{
34 public class float3x3 34 public class float3x3
35 { 35 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs
index b2b6fd3..058934d 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class float4 32 public class float4
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs
index 087eba7..58f4f58 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/float4x4.cs
@@ -30,7 +30,7 @@ using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Text; 31using System.Text;
32 32
33namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 33namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
34{ 34{
35 public class float4x4 35 public class float4x4
36 { 36 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs
index 90624eb..b3d4ecb 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int3.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class int3 32 public class int3
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs
index e9320c0..41e0912 100644
--- a/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs
+++ b/OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet/int4.cs
@@ -27,7 +27,7 @@
27 27
28using System; 28using System;
29 29
30namespace OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet 30namespace OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet
31{ 31{
32 public class int4 32 public class int4
33 { 33 {
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs
index 34a925d..a0e3b7f 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/HelperTypes.cs
@@ -31,7 +31,7 @@ using System.Diagnostics;
31using System.Globalization; 31using System.Globalization;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Region.PhysicsModules.SharedBase; 33using OpenSim.Region.PhysicsModules.SharedBase;
34using OpenSim.Region.PhysicsModules.Meshing; 34using OpenSim.Region.PhysicsModule.Meshing;
35 35
36public class Vertex : IComparable<Vertex> 36public class Vertex : IComparable<Vertex>
37{ 37{
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
index bf397ee..e63ad01 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Mesh.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.PhysicsModules.SharedBase;
33using PrimMesher; 33using PrimMesher;
34using OpenMetaverse; 34using OpenMetaverse;
35 35
36namespace OpenSim.Region.PhysicsModules.Meshing 36namespace OpenSim.Region.PhysicsModule.Meshing
37{ 37{
38 public class Mesh : IMesh 38 public class Mesh : IMesh
39 { 39 {
@@ -46,11 +46,36 @@ namespace OpenSim.Region.PhysicsModules.Meshing
46 IntPtr m_indicesPtr = IntPtr.Zero; 46 IntPtr m_indicesPtr = IntPtr.Zero;
47 int m_indexCount = 0; 47 int m_indexCount = 0;
48 public float[] m_normals; 48 public float[] m_normals;
49 Vector3 _centroid;
50 int _centroidDiv;
51
52 private class vertexcomp : IEqualityComparer<Vertex>
53 {
54 public bool Equals(Vertex v1, Vertex v2)
55 {
56 if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
57 return true;
58 else
59 return false;
60 }
61 public int GetHashCode(Vertex v)
62 {
63 int a = v.X.GetHashCode();
64 int b = v.Y.GetHashCode();
65 int c = v.Z.GetHashCode();
66 return (a << 16) ^ (b << 8) ^ c;
67 }
68
69 }
49 70
50 public Mesh() 71 public Mesh()
51 { 72 {
52 m_vertices = new Dictionary<Vertex, int>(); 73 vertexcomp vcomp = new vertexcomp();
74
75 m_vertices = new Dictionary<Vertex, int>(vcomp);
53 m_triangles = new List<Triangle>(); 76 m_triangles = new List<Triangle>();
77 _centroid = Vector3.Zero;
78 _centroidDiv = 0;
54 } 79 }
55 80
56 public Mesh Clone() 81 public Mesh Clone()
@@ -61,7 +86,8 @@ namespace OpenSim.Region.PhysicsModules.Meshing
61 { 86 {
62 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone())); 87 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
63 } 88 }
64 89 result._centroid = _centroid;
90 result._centroidDiv = _centroidDiv;
65 return result; 91 return result;
66 } 92 }
67 93
@@ -71,15 +97,63 @@ namespace OpenSim.Region.PhysicsModules.Meshing
71 throw new NotSupportedException("Attempt to Add to a pinned Mesh"); 97 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
72 // If a vertex of the triangle is not yet in the vertices list, 98 // If a vertex of the triangle is not yet in the vertices list,
73 // add it and set its index to the current index count 99 // add it and set its index to the current index count
100 // vertex == seems broken
101 // skip colapsed triangles
102 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
103 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
104 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
105 )
106 {
107 return;
108 }
109
110 if (m_vertices.Count == 0)
111 {
112 _centroidDiv = 0;
113 _centroid = Vector3.Zero;
114 }
115
74 if (!m_vertices.ContainsKey(triangle.v1)) 116 if (!m_vertices.ContainsKey(triangle.v1))
117 {
75 m_vertices[triangle.v1] = m_vertices.Count; 118 m_vertices[triangle.v1] = m_vertices.Count;
119 _centroid.X += triangle.v1.X;
120 _centroid.Y += triangle.v1.Y;
121 _centroid.Z += triangle.v1.Z;
122 _centroidDiv++;
123 }
76 if (!m_vertices.ContainsKey(triangle.v2)) 124 if (!m_vertices.ContainsKey(triangle.v2))
125 {
77 m_vertices[triangle.v2] = m_vertices.Count; 126 m_vertices[triangle.v2] = m_vertices.Count;
127 _centroid.X += triangle.v2.X;
128 _centroid.Y += triangle.v2.Y;
129 _centroid.Z += triangle.v2.Z;
130 _centroidDiv++;
131 }
78 if (!m_vertices.ContainsKey(triangle.v3)) 132 if (!m_vertices.ContainsKey(triangle.v3))
133 {
79 m_vertices[triangle.v3] = m_vertices.Count; 134 m_vertices[triangle.v3] = m_vertices.Count;
135 _centroid.X += triangle.v3.X;
136 _centroid.Y += triangle.v3.Y;
137 _centroid.Z += triangle.v3.Z;
138 _centroidDiv++;
139 }
80 m_triangles.Add(triangle); 140 m_triangles.Add(triangle);
81 } 141 }
82 142
143 public Vector3 GetCentroid()
144 {
145 if (_centroidDiv > 0)
146 return new Vector3(_centroid.X / _centroidDiv, _centroid.Y / _centroidDiv, _centroid.Z / _centroidDiv);
147 else
148 return Vector3.Zero;
149 }
150
151 // not functional
152 public Vector3 GetOBB()
153 {
154 return new Vector3(0.5f, 0.5f, 0.5f);
155 }
156
83 public void CalcNormals() 157 public void CalcNormals()
84 { 158 {
85 int iTriangles = m_triangles.Count; 159 int iTriangles = m_triangles.Count;
@@ -185,6 +259,7 @@ namespace OpenSim.Region.PhysicsModules.Meshing
185 public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount) 259 public void getVertexListAsPtrToFloatArray(out IntPtr vertices, out int vertexStride, out int vertexCount)
186 { 260 {
187 // A vertex is 3 floats 261 // A vertex is 3 floats
262
188 vertexStride = 3 * sizeof(float); 263 vertexStride = 3 * sizeof(float);
189 264
190 // If there isn't an unmanaged array allocated yet, do it now 265 // If there isn't an unmanaged array allocated yet, do it now
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs
index 4d25bf3..0d22e96 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs
@@ -44,7 +44,7 @@ using log4net;
44using Nini.Config; 44using Nini.Config;
45using Mono.Addins; 45using Mono.Addins;
46 46
47namespace OpenSim.Region.PhysicsModules.Meshing 47namespace OpenSim.Region.PhysicsModule.Meshing
48{ 48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Meshmerizer")] 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Meshmerizer")]
50 public class Meshmerizer : IMesher, INonSharedRegionModule 50 public class Meshmerizer : IMesher, INonSharedRegionModule
@@ -947,11 +947,21 @@ namespace OpenSim.Region.PhysicsModules.Meshing
947 return CreateMesh(primName, primShape, size, lod, false, true); 947 return CreateMesh(primName, primShape, size, lod, false, true);
948 } 948 }
949 949
950 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
951 {
952 return CreateMesh(primName, primShape, size, lod, false);
953 }
954
950 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 955 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
951 { 956 {
952 return CreateMesh(primName, primShape, size, lod, isPhysical, true); 957 return CreateMesh(primName, primShape, size, lod, isPhysical, true);
953 } 958 }
954 959
960 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
961 {
962 return CreateMesh(primName, primShape, size, lod, isPhysical, true);
963 }
964
955 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache) 965 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache)
956 { 966 {
957#if SPAM 967#if SPAM
@@ -1005,6 +1015,13 @@ namespace OpenSim.Region.PhysicsModules.Meshing
1005 1015
1006 return mesh; 1016 return mesh;
1007 } 1017 }
1018 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
1019 {
1020 return null;
1021 }
1008 1022
1023 public void ReleaseMesh(IMesh imesh) { }
1024 public void ExpireReleaseMeshs() { }
1025 public void ExpireFileCache() { }
1009 } 1026 }
1010} 1027}
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs
index 740424e..b3d9cb6 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/SculptMap.cs
@@ -58,28 +58,24 @@ namespace PrimMesher
58 if (bmW == 0 || bmH == 0) 58 if (bmW == 0 || bmH == 0)
59 throw new Exception("SculptMap: bitmap has no data"); 59 throw new Exception("SculptMap: bitmap has no data");
60 60
61 int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image 61 int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image
62 62
63 bool smallMap = bmW * bmH <= numLodPixels;
63 bool needsScaling = false; 64 bool needsScaling = false;
64 65
65 bool smallMap = bmW * bmH <= lod * lod;
66
67 width = bmW; 66 width = bmW;
68 height = bmH; 67 height = bmH;
69 while (width * height > numLodPixels) 68 while (width * height > numLodPixels * 4)
70 { 69 {
71 width >>= 1; 70 width >>= 1;
72 height >>= 1; 71 height >>= 1;
73 needsScaling = true; 72 needsScaling = true;
74 } 73 }
75 74
76
77
78 try 75 try
79 { 76 {
80 if (needsScaling) 77 if (needsScaling)
81 bm = ScaleImage(bm, width, height, 78 bm = ScaleImage(bm, width, height);
82 System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor);
83 } 79 }
84 80
85 catch (Exception e) 81 catch (Exception e)
@@ -87,7 +83,7 @@ namespace PrimMesher
87 throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); 83 throw new Exception("Exception in ScaleImage(): e: " + e.ToString());
88 } 84 }
89 85
90 if (width * height > lod * lod) 86 if (width * height > numLodPixels)
91 { 87 {
92 width >>= 1; 88 width >>= 1;
93 height >>= 1; 89 height >>= 1;
@@ -144,15 +140,17 @@ namespace PrimMesher
144 int rowNdx, colNdx; 140 int rowNdx, colNdx;
145 int smNdx = 0; 141 int smNdx = 0;
146 142
143
147 for (rowNdx = 0; rowNdx < numRows; rowNdx++) 144 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
148 { 145 {
149 List<Coord> row = new List<Coord>(numCols); 146 List<Coord> row = new List<Coord>(numCols);
150 for (colNdx = 0; colNdx < numCols; colNdx++) 147 for (colNdx = 0; colNdx < numCols; colNdx++)
151 { 148 {
149
152 if (mirror) 150 if (mirror)
153 row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f)); 151 row.Add(new Coord(-((float)redBytes[smNdx] * pixScale - 0.5f), ((float)greenBytes[smNdx] * pixScale - 0.5f), (float)blueBytes[smNdx] * pixScale - 0.5f));
154 else 152 else
155 row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f)); 153 row.Add(new Coord((float)redBytes[smNdx] * pixScale - 0.5f, (float)greenBytes[smNdx] * pixScale - 0.5f, (float)blueBytes[smNdx] * pixScale - 0.5f));
156 154
157 ++smNdx; 155 ++smNdx;
158 } 156 }
@@ -161,23 +159,39 @@ namespace PrimMesher
161 return rows; 159 return rows;
162 } 160 }
163 161
164 private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight, 162 private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight)
165 System.Drawing.Drawing2D.InterpolationMode interpMode)
166 { 163 {
167 Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight);
168 scaledImage.SetResolution(96.0f, 96.0f);
169
170 Graphics grPhoto = Graphics.FromImage(scaledImage);
171 grPhoto.InterpolationMode = interpMode;
172 164
173 grPhoto.DrawImage(srcImage, 165 Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
174 new Rectangle(0, 0, destWidth, destHeight), 166
175 new Rectangle(0, 0, srcImage.Width, srcImage.Height), 167 Color c;
176 GraphicsUnit.Pixel); 168 float xscale = srcImage.Width / destWidth;
169 float yscale = srcImage.Height / destHeight;
170
171 float sy = 0.5f;
172 for (int y = 0; y < destHeight; y++)
173 {
174 float sx = 0.5f;
175 for (int x = 0; x < destWidth; x++)
176 {
177 try
178 {
179 c = srcImage.GetPixel((int)(sx), (int)(sy));
180 scaledImage.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B));
181 }
182 catch (IndexOutOfRangeException)
183 {
184 }
177 185
178 grPhoto.Dispose(); 186 sx += xscale;
187 }
188 sy += yscale;
189 }
190 srcImage.Dispose();
179 return scaledImage; 191 return scaledImage;
180 } 192 }
193
194 }
195
181 } 196 }
182}
183#endif 197#endif
diff --git a/OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs
index b4bdb5a..3e17990 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/Properties/AssemblyInfo.cs
@@ -6,7 +6,7 @@ using Mono.Addins;
6// General Information about an assembly is controlled through the following 6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information 7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly. 8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Region.PhysicsModules.Meshing")] 9[assembly: AssemblyTitle("OpenSim.Region.PhysicsModule.Meshing")]
10[assembly: AssemblyDescription("")] 10[assembly: AssemblyDescription("")]
11[assembly: AssemblyConfiguration("")] 11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("http://opensimulator.org")] 12[assembly: AssemblyCompany("http://opensimulator.org")]
@@ -32,5 +32,5 @@ using Mono.Addins;
32// 32//
33[assembly: AssemblyVersion("0.8.3.*")] 33[assembly: AssemblyVersion("0.8.3.*")]
34 34
35[assembly: Addin("OpenSim.Region.PhysicsModules.Meshing", OpenSim.VersionInfo.VersionNumber)] 35[assembly: Addin("OpenSim.Region.PhysicsModule.Meshing", OpenSim.VersionInfo.VersionNumber)]
36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] 36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs b/OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs
index 0a3b3a4..dbf4f7e 100644
--- a/OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs
+++ b/OpenSim/Region/PhysicsModules/Meshing/ZeroMesher.cs
@@ -47,7 +47,7 @@ using log4net;
47 * it's always availabe and thus the default in case of configuration errors 47 * it's always availabe and thus the default in case of configuration errors
48*/ 48*/
49 49
50namespace OpenSim.Region.PhysicsModules.Meshing 50namespace OpenSim.Region.PhysicsModule.Meshing
51{ 51{
52 52
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ZeroMesher")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ZeroMesher")]
@@ -110,23 +110,36 @@ namespace OpenSim.Region.PhysicsModules.Meshing
110 #region IMesher 110 #region IMesher
111 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 111 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
112 { 112 {
113 return CreateMesh(primName, primShape, size, lod, false, false); 113 return CreateMesh(primName, primShape, size, lod, false);
114 } 114 }
115 115
116 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical) 116 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
117 {
118 return CreateMesh(primName, primShape, size, lod, false);
119 }
120
121 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex,bool forOde)
117 { 122 {
118 return CreateMesh(primName, primShape, size, lod, false, false); 123 return CreateMesh(primName, primShape, size, lod, false);
119 } 124 }
120 125
121 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache) 126 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
122 { 127 {
123 // Remove the reference to the encoded JPEG2000 data so it can be GCed 128 // Remove the reference to the encoded JPEG2000 data so it can be GCed
124 primShape.SculptData = OpenMetaverse.Utils.EmptyBytes; 129 primShape.SculptData = OpenMetaverse.Utils.EmptyBytes;
125 130
126 return null; 131 return null;
127 } 132 }
128 #endregion
129 133
134 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
135 {
136 return null;
137 }
130 138
139 public void ReleaseMesh(IMesh mesh) { }
140 public void ExpireReleaseMeshs() { }
141 public void ExpireFileCache() { }
142
143 #endregion
131 } 144 }
132} 145}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs b/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs
index b35c299..c1afe13 100644
--- a/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/ODECharacter.cs
@@ -595,7 +595,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
595 595
596 public override void delink() {} 596 public override void delink() {}
597 597
598 public override void LockAngularMotion(Vector3 axis) {} 598 public override void LockAngularMotion(byte axislocks) {}
599 599
600// This code is very useful. Written by DanX0r. We're just not using it right now. 600// This code is very useful. Written by DanX0r. We're just not using it right now.
601// Commented out to prevent a warning. 601// Commented out to prevent a warning.
@@ -1257,7 +1257,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
1257 public override float PIDTau { set { return; } } 1257 public override float PIDTau { set { return; } }
1258 1258
1259 public override float PIDHoverHeight { set { return; } } 1259 public override float PIDHoverHeight { set { return; } }
1260 public override bool PIDHoverActive { set { return; } } 1260 public override bool PIDHoverActive {get {return false;} set { return; } }
1261 public override PIDHoverType PIDHoverType { set { return; } } 1261 public override PIDHoverType PIDHoverType { set { return; } }
1262 public override float PIDHoverTau { set { return; } } 1262 public override float PIDHoverTau { set { return; } }
1263 1263
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs b/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs
new file mode 100644
index 0000000..101e8b0
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEModule.cs
@@ -0,0 +1,85 @@
1using System;
2using System.Reflection;
3using log4net;
4using Nini.Config;
5using Mono.Addins;
6using OpenSim.Framework;
7using OpenSim.Region.Framework.Scenes;
8using OpenSim.Region.Framework.Interfaces;
9using Ode.NET;
10
11namespace OpenSim.Region.PhysicsModule.ODE
12{
13 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ODEPhysicsScene")]
14 public class OdeModule : INonSharedRegionModule
15 {
16 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
17
18 private bool m_Enabled = false;
19 private IConfigSource m_config;
20 private OdeScene m_scene;
21
22 #region INonSharedRegionModule
23
24 public string Name
25 {
26 get { return "OpenDynamicsEngine"; }
27 }
28
29 public Type ReplaceableInterface
30 {
31 get { return null; }
32 }
33
34 public void Initialise(IConfigSource source)
35 {
36 IConfig config = source.Configs["Startup"];
37 if (config != null)
38 {
39 string physics = config.GetString("physics", string.Empty);
40 if (physics == Name)
41 {
42 m_config = source;
43 m_Enabled = true;
44 }
45 }
46 }
47
48 public void Close()
49 {
50 }
51
52 public void AddRegion(Scene scene)
53 {
54 if (!m_Enabled)
55 return;
56
57 if (Util.IsWindows())
58 Util.LoadArchSpecificWindowsDll("ode.dll");
59
60 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
61 // http://opensimulator.org/mantis/view.php?id=2750).
62 d.InitODE();
63
64 m_scene = new OdeScene(scene, m_config, Name);
65 }
66
67 public void RemoveRegion(Scene scene)
68 {
69 if (!m_Enabled || m_scene == null)
70 return;
71
72 m_scene.Dispose();
73 m_scene = null;
74 }
75
76 public void RegionLoaded(Scene scene)
77 {
78 if (!m_Enabled || m_scene == null)
79 return;
80
81 m_scene.RegionLoaded();
82 }
83 #endregion
84 }
85}
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs b/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs
index 0b9c45f..908b266 100644
--- a/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/ODEPrim.cs
@@ -83,8 +83,15 @@ namespace OpenSim.Region.PhysicsModule.ODE
83 set 83 set
84 { 84 {
85 m_isphysical = value; 85 m_isphysical = value;
86 if (!m_isphysical) // Zero the remembered last velocity 86 if (!m_isphysical)
87 {
88 _zeroFlag = true; // Zero the remembered last velocity
87 m_lastVelocity = Vector3.Zero; 89 m_lastVelocity = Vector3.Zero;
90 _acceleration = Vector3.Zero;
91 _velocity = Vector3.Zero;
92 m_taintVelocity = Vector3.Zero;
93 m_rotationalVelocity = Vector3.Zero;
94 }
88 } 95 }
89 } 96 }
90 97
@@ -104,10 +111,12 @@ namespace OpenSim.Region.PhysicsModule.ODE
104 private Vector3 m_taintVelocity; 111 private Vector3 m_taintVelocity;
105 private Vector3 m_taintTorque; 112 private Vector3 m_taintTorque;
106 private Quaternion m_taintrot; 113 private Quaternion m_taintrot;
107 private Vector3 m_angularlock = Vector3.One; 114
108 private Vector3 m_taintAngularLock = Vector3.One;
109 private IntPtr Amotor = IntPtr.Zero; 115 private IntPtr Amotor = IntPtr.Zero;
110 116
117 private byte m_taintAngularLock = 0;
118 private byte m_angularlock = 0;
119
111 private bool m_assetFailed = false; 120 private bool m_assetFailed = false;
112 121
113 private Vector3 m_PIDTarget; 122 private Vector3 m_PIDTarget;
@@ -445,7 +454,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
445 m_disabled = false; 454 m_disabled = false;
446 455
447 // The body doesn't already have a finite rotation mode set here 456 // The body doesn't already have a finite rotation mode set here
448 if ((!m_angularlock.ApproxEquals(Vector3.One, 0.0f)) && _parent == null) 457 if (m_angularlock != 0 && _parent == null)
449 { 458 {
450 createAMotor(m_angularlock); 459 createAMotor(m_angularlock);
451 } 460 }
@@ -919,7 +928,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
919// _parent_scene.waitForSpaceUnlock(m_targetSpace); 928// _parent_scene.waitForSpaceUnlock(m_targetSpace);
920 try 929 try
921 { 930 {
922 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); 931 SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null));
923 } 932 }
924 catch (AccessViolationException) 933 catch (AccessViolationException)
925 { 934 {
@@ -1001,7 +1010,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1001 if (m_taintCollidesWater != m_collidesWater) 1010 if (m_taintCollidesWater != m_collidesWater)
1002 changefloatonwater(); 1011 changefloatonwater();
1003 1012
1004 if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) 1013 if (m_taintAngularLock != m_angularlock)
1005 changeAngularLock(); 1014 changeAngularLock();
1006 } 1015 }
1007 1016
@@ -1017,10 +1026,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1017 //If we have a parent then we're not authorative here 1026 //If we have a parent then we're not authorative here
1018 if (_parent == null) 1027 if (_parent == null)
1019 { 1028 {
1020 if (!m_taintAngularLock.ApproxEquals(Vector3.One, 0f)) 1029 if (m_taintAngularLock != 0)
1021 { 1030 {
1022 //d.BodySetFiniteRotationMode(Body, 0);
1023 //d.BodySetFiniteRotationAxis(Body,m_taintAngularLock.X,m_taintAngularLock.Y,m_taintAngularLock.Z);
1024 createAMotor(m_taintAngularLock); 1031 createAMotor(m_taintAngularLock);
1025 } 1032 }
1026 else 1033 else
@@ -1034,7 +1041,6 @@ Console.WriteLine("ZProcessTaints for " + Name);
1034 } 1041 }
1035 } 1042 }
1036 1043
1037 // Store this for later in case we get turned into a separate body
1038 m_angularlock = m_taintAngularLock; 1044 m_angularlock = m_taintAngularLock;
1039 } 1045 }
1040 1046
@@ -1230,7 +1236,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1230 m_disabled = false; 1236 m_disabled = false;
1231 1237
1232 // The body doesn't already have a finite rotation mode set here 1238 // The body doesn't already have a finite rotation mode set here
1233 if ((!m_angularlock.ApproxEquals(Vector3.One, 0f)) && _parent == null) 1239 // or remove
1240 if (_parent == null)
1234 { 1241 {
1235 createAMotor(m_angularlock); 1242 createAMotor(m_angularlock);
1236 } 1243 }
@@ -1686,6 +1693,9 @@ Console.WriteLine(" JointCreateFixed");
1686 float fy = 0; 1693 float fy = 0;
1687 float fz = 0; 1694 float fz = 0;
1688 1695
1696 if (outofBounds)
1697 return;
1698
1689 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. 1699 if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims.
1690 { 1700 {
1691 if (m_vehicle.Type != Vehicle.TYPE_NONE) 1701 if (m_vehicle.Type != Vehicle.TYPE_NONE)
@@ -1697,21 +1707,6 @@ Console.WriteLine(" JointCreateFixed");
1697 { 1707 {
1698//Console.WriteLine("Move " + Name); 1708//Console.WriteLine("Move " + Name);
1699 if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 1709 if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
1700 // NON-'VEHICLES' are dealt with here
1701// if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f))
1702// {
1703// d.Vector3 avel2 = d.BodyGetAngularVel(Body);
1704// /*
1705// if (m_angularlock.X == 1)
1706// avel2.X = 0;
1707// if (m_angularlock.Y == 1)
1708// avel2.Y = 0;
1709// if (m_angularlock.Z == 1)
1710// avel2.Z = 0;
1711// d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z);
1712// */
1713// }
1714 //float PID_P = 900.0f;
1715 1710
1716 float m_mass = CalculateMass(); 1711 float m_mass = CalculateMass();
1717 1712
@@ -1940,8 +1935,8 @@ Console.WriteLine(" JointCreateFixed");
1940 d.BodySetQuaternion(Body, ref myrot); 1935 d.BodySetQuaternion(Body, ref myrot);
1941 if (IsPhysical) 1936 if (IsPhysical)
1942 { 1937 {
1943 if (!m_angularlock.ApproxEquals(Vector3.One, 0f)) 1938 // create or remove locks
1944 createAMotor(m_angularlock); 1939 createAMotor(m_angularlock);
1945 } 1940 }
1946 } 1941 }
1947 else 1942 else
@@ -2659,16 +2654,38 @@ Console.WriteLine(" JointCreateFixed");
2659 2654
2660 public override void CrossingFailure() 2655 public override void CrossingFailure()
2661 { 2656 {
2662 m_crossingfailures++; 2657 /*
2663 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds) 2658 m_crossingfailures++;
2664 { 2659 if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2665 base.RaiseOutOfBounds(_position); 2660 {
2666 return; 2661 base.RaiseOutOfBounds(_position);
2667 } 2662 return;
2668 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds) 2663 }
2664 else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2665 {
2666 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + Name);
2667 }
2668 */
2669 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
2670 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
2671 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
2672
2673 m_lastposition = _position;
2674 _velocity.X = 0;
2675 _velocity.Y = 0;
2676 _velocity.Z = 0;
2677
2678 m_lastVelocity = _velocity;
2679
2680 if (Body != IntPtr.Zero)
2669 { 2681 {
2670 m_log.Warn("[PHYSICS]: Too many crossing failures for: " + Name); 2682 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
2683 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
2671 } 2684 }
2685
2686 outofBounds = false;
2687 base.RequestPhysicsterseUpdate();
2688
2672 } 2689 }
2673 2690
2674 public override float Buoyancy 2691 public override float Buoyancy
@@ -2687,32 +2704,23 @@ Console.WriteLine(" JointCreateFixed");
2687 m_taintparent = null; 2704 m_taintparent = null;
2688 } 2705 }
2689 2706
2690 public override void LockAngularMotion(Vector3 axis) 2707 public override void LockAngularMotion(byte axislocks)
2691 { 2708 {
2692 // reverse the zero/non zero values for ODE. 2709 // m_log.DebugFormat("[axislocks]: {0}", axislocks);
2693 if (axis.IsFinite()) 2710 m_taintAngularLock = axislocks;
2694 {
2695 axis.X = (axis.X > 0) ? 1f : 0f;
2696 axis.Y = (axis.Y > 0) ? 1f : 0f;
2697 axis.Z = (axis.Z > 0) ? 1f : 0f;
2698 m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
2699 m_taintAngularLock = axis;
2700 }
2701 else
2702 {
2703 m_log.WarnFormat("[PHYSICS]: Got NaN locking axis from Scene on Object {0}", Name);
2704 }
2705 } 2711 }
2706 2712
2707 internal void UpdatePositionAndVelocity() 2713 internal void UpdatePositionAndVelocity()
2708 { 2714 {
2709 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 2715 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
2716 if (outofBounds)
2717 return;
2710 if (_parent == null) 2718 if (_parent == null)
2711 { 2719 {
2712 Vector3 pv = Vector3.Zero; 2720 Vector3 pv = Vector3.Zero;
2713 bool lastZeroFlag = _zeroFlag; 2721 bool lastZeroFlag = _zeroFlag;
2714 float m_minvelocity = 0; 2722 float m_minvelocity = 0;
2715 if (Body != (IntPtr)0) // FIXME -> or if it is a joint 2723 if (Body != IntPtr.Zero) // FIXME -> or if it is a joint
2716 { 2724 {
2717 d.Vector3 vec = d.BodyGetPosition(Body); 2725 d.Vector3 vec = d.BodyGetPosition(Body);
2718 d.Quaternion ori = d.BodyGetQuaternion(Body); 2726 d.Quaternion ori = d.BodyGetQuaternion(Body);
@@ -2723,12 +2731,6 @@ Console.WriteLine(" JointCreateFixed");
2723 Vector3 l_position = Vector3.Zero; 2731 Vector3 l_position = Vector3.Zero;
2724 Quaternion l_orientation = Quaternion.Identity; 2732 Quaternion l_orientation = Quaternion.Identity;
2725 2733
2726 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
2727 //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
2728 //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
2729 //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
2730 //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); }
2731
2732 m_lastposition = _position; 2734 m_lastposition = _position;
2733 m_lastorientation = _orientation; 2735 m_lastorientation = _orientation;
2734 2736
@@ -2740,26 +2742,6 @@ Console.WriteLine(" JointCreateFixed");
2740 l_orientation.Z = ori.Z; 2742 l_orientation.Z = ori.Z;
2741 l_orientation.W = ori.W; 2743 l_orientation.W = ori.W;
2742 2744
2743 if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f)
2744 {
2745 //base.RaiseOutOfBounds(l_position);
2746
2747 if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2748 {
2749 _position = l_position;
2750 //_parent_scene.remActivePrim(this);
2751 if (_parent == null)
2752 base.RequestPhysicsterseUpdate();
2753 return;
2754 }
2755 else
2756 {
2757 if (_parent == null)
2758 base.RaiseOutOfBounds(l_position);
2759 return;
2760 }
2761 }
2762
2763 if (l_position.Z < 0) 2745 if (l_position.Z < 0)
2764 { 2746 {
2765 // This is so prim that get lost underground don't fall forever and suck up 2747 // This is so prim that get lost underground don't fall forever and suck up
@@ -2769,8 +2751,6 @@ Console.WriteLine(" JointCreateFixed");
2769 // It's a hack and will generate a console message if it fails. 2751 // It's a hack and will generate a console message if it fails.
2770 2752
2771 //IsPhysical = false; 2753 //IsPhysical = false;
2772 if (_parent == null)
2773 base.RaiseOutOfBounds(_position);
2774 2754
2775 _acceleration.X = 0; 2755 _acceleration.X = 0;
2776 _acceleration.Y = 0; 2756 _acceleration.Y = 0;
@@ -2784,16 +2764,64 @@ Console.WriteLine(" JointCreateFixed");
2784 m_rotationalVelocity.Z = 0; 2764 m_rotationalVelocity.Z = 0;
2785 2765
2786 if (_parent == null) 2766 if (_parent == null)
2767 base.RaiseOutOfBounds(_position);
2768
2769 if (_parent == null)
2787 base.RequestPhysicsterseUpdate(); 2770 base.RequestPhysicsterseUpdate();
2788 2771
2789 m_throttleUpdates = false; 2772 m_throttleUpdates = false;
2790 throttleCounter = 0; 2773 throttleCounter = 0;
2791 _zeroFlag = true; 2774 _zeroFlag = true;
2792 //outofBounds = true; 2775 //outofBounds = true;
2776 return;
2777 }
2778
2779 if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f)
2780 {
2781 //base.RaiseOutOfBounds(l_position);
2782 /*
2783 if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds)
2784 {
2785 _position = l_position;
2786 //_parent_scene.remActivePrim(this);
2787 if (_parent == null)
2788 base.RequestPhysicsterseUpdate();
2789 return;
2790 }
2791 else
2792 {
2793 if (_parent == null)
2794 base.RaiseOutOfBounds(l_position);
2795 return;
2796 }
2797 */
2798 outofBounds = true;
2799 // part near the border on outside
2800 if (l_position.X < 0)
2801 Util.Clamp(l_position.X, -0.1f, -2f);
2802 else
2803 Util.Clamp(l_position.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
2804 if (l_position.Y < 0)
2805 Util.Clamp(l_position.Y, -0.1f, -2f);
2806 else
2807 Util.Clamp(l_position.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
2808
2809 d.BodySetPosition(Body, l_position.X, l_position.Y, l_position.Z);
2810
2811 // stop it
2812 d.BodySetAngularVel(Body, 0, 0, 0);
2813 d.BodySetLinearVel(Body, 0, 0, 0);
2814 disableBodySoft();
2815
2816 // tell framework to fix it
2817 if (_parent == null)
2818 base.RequestPhysicsterseUpdate();
2819 return;
2793 } 2820 }
2794 2821
2822
2795 //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); 2823 //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation));
2796//Console.WriteLine("Adiff " + Name + " = " + Adiff); 2824 //Console.WriteLine("Adiff " + Name + " = " + Adiff);
2797 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) 2825 if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02)
2798 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) 2826 && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02)
2799 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) 2827 && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02)
@@ -2950,11 +2978,12 @@ Console.WriteLine(" JointCreateFixed");
2950 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name); 2978 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
2951 } 2979 }
2952 } 2980 }
2981
2953 public override bool PIDActive { get; set; } 2982 public override bool PIDActive { get; set; }
2954 public override float PIDTau { set { m_PIDTau = value; } } 2983 public override float PIDTau { set { m_PIDTau = value; } }
2955 2984
2956 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } 2985 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
2957 public override bool PIDHoverActive { set { m_useHoverPID = value; } } 2986 public override bool PIDHoverActive { get { return m_useHoverPID;} set { m_useHoverPID = value; } }
2958 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } 2987 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
2959 public override float PIDHoverTau { set { m_PIDHoverTau = value; } } 2988 public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
2960 2989
@@ -2966,7 +2995,7 @@ Console.WriteLine(" JointCreateFixed");
2966 2995
2967 public override float APIDDamping{ set { return; } } 2996 public override float APIDDamping{ set { return; } }
2968 2997
2969 private void createAMotor(Vector3 axis) 2998 private void createAMotor(byte axislock)
2970 { 2999 {
2971 if (Body == IntPtr.Zero) 3000 if (Body == IntPtr.Zero)
2972 return; 3001 return;
@@ -2977,150 +3006,105 @@ Console.WriteLine(" JointCreateFixed");
2977 Amotor = IntPtr.Zero; 3006 Amotor = IntPtr.Zero;
2978 } 3007 }
2979 3008
2980 float axisnum = 3; 3009 if(axislock == 0)
2981 3010 return;
2982 axisnum = (axisnum - (axis.X + axis.Y + axis.Z));
2983
2984 // PhysicsVector totalSize = new PhysicsVector(_size.X, _size.Y, _size.Z);
2985
2986
2987 // Inverse Inertia Matrix, set the X, Y, and/r Z inertia to 0 then invert it again.
2988 d.Mass objMass;
2989 d.MassSetZero(out objMass);
2990 DMassCopy(ref pMass, ref objMass);
2991
2992 //m_log.DebugFormat("1-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22);
2993
2994 Matrix4 dMassMat = FromDMass(objMass);
2995
2996 Matrix4 mathmat = Inverse(dMassMat);
2997
2998 /*
2999 //m_log.DebugFormat("2-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", mathmat[0, 0], mathmat[0, 1], mathmat[0, 2], mathmat[1, 0], mathmat[1, 1], mathmat[1, 2], mathmat[2, 0], mathmat[2, 1], mathmat[2, 2]);
3000
3001 mathmat = Inverse(mathmat);
3002
3003
3004 objMass = FromMatrix4(mathmat, ref objMass);
3005 //m_log.DebugFormat("3-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22);
3006
3007 mathmat = Inverse(mathmat);
3008 */
3009 if (axis.X == 0)
3010 {
3011 mathmat.M33 = 50.0000001f;
3012 //objMass.I.M22 = 0;
3013 }
3014 if (axis.Y == 0)
3015 {
3016 mathmat.M22 = 50.0000001f;
3017 //objMass.I.M11 = 0;
3018 }
3019 if (axis.Z == 0)
3020 {
3021 mathmat.M11 = 50.0000001f;
3022 //objMass.I.M00 = 0;
3023 }
3024
3025
3026 3011
3027 mathmat = Inverse(mathmat); 3012 int axisnum = 0;
3028 objMass = FromMatrix4(mathmat, ref objMass); 3013 bool axisX = false;
3029 //m_log.DebugFormat("4-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); 3014 bool axisY = false;
3030 3015 bool axisZ = false;
3031 //return; 3016 if((axislock & 0x02) != 0)
3032 if (d.MassCheck(ref objMass)) 3017 {
3033 { 3018 axisnum++;
3034 d.BodySetMass(Body, ref objMass); 3019 axisX = true;
3035 } 3020 }
3036 else 3021 if((axislock & 0x04) != 0)
3037 { 3022 {
3038 //m_log.Debug("[PHYSICS]: Mass invalid, ignoring"); 3023 axisnum++;
3039 } 3024 axisY = true;
3025 }
3026 if((axislock & 0x08) != 0)
3027 {
3028 axisnum++;
3029 axisZ = true;
3030 }
3040 3031
3041 if (axisnum <= 0) 3032 if(axisnum == 0)
3042 return; 3033 return;
3043 // int dAMotorEuler = 1; 3034 // stop it
3035 d.BodySetTorque(Body, 0, 0, 0);
3036 d.BodySetAngularVel(Body, 0, 0, 0);
3044 3037
3045 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); 3038 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
3046 d.JointAttach(Amotor, Body, IntPtr.Zero); 3039 d.JointAttach(Amotor, Body, IntPtr.Zero);
3040
3047 d.JointSetAMotorMode(Amotor, 0); 3041 d.JointSetAMotorMode(Amotor, 0);
3048 3042
3049 d.JointSetAMotorNumAxes(Amotor,(int)axisnum); 3043 d.JointSetAMotorNumAxes(Amotor, axisnum);
3050 int i = 0;
3051 3044
3052 if (axis.X == 0) 3045 // get current orientation to lock
3053 {
3054 d.JointSetAMotorAxis(Amotor, i, 0, 1, 0, 0);
3055 i++;
3056 }
3057 3046
3058 if (axis.Y == 0) 3047 d.Quaternion dcur = d.BodyGetQuaternion(Body);
3059 { 3048 Quaternion curr; // crap convertion between identical things
3060 d.JointSetAMotorAxis(Amotor, i, 0, 0, 1, 0); 3049 curr.X = dcur.X;
3061 i++; 3050 curr.Y = dcur.Y;
3062 } 3051 curr.Z = dcur.Z;
3052 curr.W = dcur.W;
3053 Vector3 ax;
3063 3054
3064 if (axis.Z == 0) 3055 int i = 0;
3065 { 3056 int j = 0;
3066 d.JointSetAMotorAxis(Amotor, i, 0, 0, 0, 1); 3057 if (axisX)
3058 {
3059 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
3060 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
3061 d.JointSetAMotorAngle(Amotor, 0, 0);
3062 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, 0f);
3063 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0f);
3064 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
3065 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
3066 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
3067 d.JointSetAMotorParam(Amotor, (int)d.JointParam.CFM, 0f);
3068 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
3069 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
3070 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
3071 i++;
3072 j = 256; // move to next axis set
3073 }
3074
3075 if (axisY)
3076 {
3077 ax = (new Vector3(0, 1, 0)) * curr;
3078 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
3079 d.JointSetAMotorAngle(Amotor, i, 0);
3080 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
3081 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
3082 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
3083 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
3084 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
3085 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
3086 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
3087 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
3088 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
3067 i++; 3089 i++;
3090 j += 256;
3068 } 3091 }
3069 3092
3070 for (int j = 0; j < (int)axisnum; j++) 3093 if (axisZ)
3071 { 3094 {
3072 //d.JointSetAMotorAngle(Amotor, j, 0); 3095 ax = (new Vector3(0, 0, 1)) * curr;
3096 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
3097 d.JointSetAMotorAngle(Amotor, i, 0);
3098 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
3099 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
3100 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
3101 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
3102 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
3103 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
3104 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
3105 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
3106 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
3073 } 3107 }
3074
3075 //d.JointSetAMotorAngle(Amotor, 1, 0);
3076 //d.JointSetAMotorAngle(Amotor, 2, 0);
3077
3078 // These lowstops and high stops are effectively (no wiggle room)
3079 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0f);
3080 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
3081 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0f);
3082 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f);
3083 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f);
3084 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f);
3085 //d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 9000f);
3086 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
3087 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, Mass * 50f);//
3088 }
3089
3090 private Matrix4 FromDMass(d.Mass pMass)
3091 {
3092 Matrix4 obj;
3093 obj.M11 = pMass.I.M00;
3094 obj.M12 = pMass.I.M01;
3095 obj.M13 = pMass.I.M02;
3096 obj.M14 = 0;
3097 obj.M21 = pMass.I.M10;
3098 obj.M22 = pMass.I.M11;
3099 obj.M23 = pMass.I.M12;
3100 obj.M24 = 0;
3101 obj.M31 = pMass.I.M20;
3102 obj.M32 = pMass.I.M21;
3103 obj.M33 = pMass.I.M22;
3104 obj.M34 = 0;
3105 obj.M41 = 0;
3106 obj.M42 = 0;
3107 obj.M43 = 0;
3108 obj.M44 = 1;
3109 return obj;
3110 }
3111
3112 private d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj)
3113 {
3114 obj.I.M00 = pMat[0, 0];
3115 obj.I.M01 = pMat[0, 1];
3116 obj.I.M02 = pMat[0, 2];
3117 obj.I.M10 = pMat[1, 0];
3118 obj.I.M11 = pMat[1, 1];
3119 obj.I.M12 = pMat[1, 2];
3120 obj.I.M20 = pMat[2, 0];
3121 obj.I.M21 = pMat[2, 1];
3122 obj.I.M22 = pMat[2, 2];
3123 return obj;
3124 } 3108 }
3125 3109
3126 public override void SubscribeEvents(int ms) 3110 public override void SubscribeEvents(int ms)
@@ -3165,173 +3149,6 @@ Console.WriteLine(" JointCreateFixed");
3165 return false; 3149 return false;
3166 } 3150 }
3167 3151
3168 public static Matrix4 Inverse(Matrix4 pMat)
3169 {
3170 if (determinant3x3(pMat) == 0)
3171 {
3172 return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible
3173 }
3174
3175 return (Adjoint(pMat) / determinant3x3(pMat));
3176 }
3177
3178 public static Matrix4 Adjoint(Matrix4 pMat)
3179 {
3180 Matrix4 adjointMatrix = new Matrix4();
3181 for (int i=0; i<4; i++)
3182 {
3183 for (int j=0; j<4; j++)
3184 {
3185 Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j)))));
3186 }
3187 }
3188
3189 adjointMatrix = Transpose(adjointMatrix);
3190 return adjointMatrix;
3191 }
3192
3193 public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol)
3194 {
3195 Matrix4 minor = new Matrix4();
3196 int m = 0, n = 0;
3197 for (int i = 0; i < 4; i++)
3198 {
3199 if (i == iRow)
3200 continue;
3201 n = 0;
3202 for (int j = 0; j < 4; j++)
3203 {
3204 if (j == iCol)
3205 continue;
3206 Matrix4SetValue(ref minor, m,n, matrix[i, j]);
3207 n++;
3208 }
3209 m++;
3210 }
3211
3212 return minor;
3213 }
3214
3215 public static Matrix4 Transpose(Matrix4 pMat)
3216 {
3217 Matrix4 transposeMatrix = new Matrix4();
3218 for (int i = 0; i < 4; i++)
3219 for (int j = 0; j < 4; j++)
3220 Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]);
3221 return transposeMatrix;
3222 }
3223
3224 public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val)
3225 {
3226 switch (r)
3227 {
3228 case 0:
3229 switch (c)
3230 {
3231 case 0:
3232 pMat.M11 = val;
3233 break;
3234 case 1:
3235 pMat.M12 = val;
3236 break;
3237 case 2:
3238 pMat.M13 = val;
3239 break;
3240 case 3:
3241 pMat.M14 = val;
3242 break;
3243 }
3244
3245 break;
3246 case 1:
3247 switch (c)
3248 {
3249 case 0:
3250 pMat.M21 = val;
3251 break;
3252 case 1:
3253 pMat.M22 = val;
3254 break;
3255 case 2:
3256 pMat.M23 = val;
3257 break;
3258 case 3:
3259 pMat.M24 = val;
3260 break;
3261 }
3262
3263 break;
3264 case 2:
3265 switch (c)
3266 {
3267 case 0:
3268 pMat.M31 = val;
3269 break;
3270 case 1:
3271 pMat.M32 = val;
3272 break;
3273 case 2:
3274 pMat.M33 = val;
3275 break;
3276 case 3:
3277 pMat.M34 = val;
3278 break;
3279 }
3280
3281 break;
3282 case 3:
3283 switch (c)
3284 {
3285 case 0:
3286 pMat.M41 = val;
3287 break;
3288 case 1:
3289 pMat.M42 = val;
3290 break;
3291 case 2:
3292 pMat.M43 = val;
3293 break;
3294 case 3:
3295 pMat.M44 = val;
3296 break;
3297 }
3298
3299 break;
3300 }
3301 }
3302
3303 private static float determinant3x3(Matrix4 pMat)
3304 {
3305 float det = 0;
3306 float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2];
3307 float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0];
3308 float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1];
3309 float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2];
3310 float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0];
3311 float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1];
3312
3313 det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6);
3314 return det;
3315 }
3316
3317 private static void DMassCopy(ref d.Mass src, ref d.Mass dst)
3318 {
3319 dst.c.W = src.c.W;
3320 dst.c.X = src.c.X;
3321 dst.c.Y = src.c.Y;
3322 dst.c.Z = src.c.Z;
3323 dst.mass = src.mass;
3324 dst.I.M00 = src.I.M00;
3325 dst.I.M01 = src.I.M01;
3326 dst.I.M02 = src.I.M02;
3327 dst.I.M10 = src.I.M10;
3328 dst.I.M11 = src.I.M11;
3329 dst.I.M12 = src.I.M12;
3330 dst.I.M20 = src.I.M20;
3331 dst.I.M21 = src.I.M21;
3332 dst.I.M22 = src.I.M22;
3333 }
3334
3335 public override void SetMaterial(int pMaterial) 3152 public override void SetMaterial(int pMaterial)
3336 { 3153 {
3337 m_material = pMaterial; 3154 m_material = pMaterial;
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
index 8d610f7..6199387 100644
--- a/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/ODERayCastRequestManager.cs
@@ -180,7 +180,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
180 len = 250f; 180 len = 250f;
181 181
182 // Create the ray 182 // Create the ray
183 IntPtr ray = d.CreateRay(m_scene.space, req.length); 183 IntPtr ray = d.CreateRay(m_scene.space, len);
184 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); 184 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
185 185
186 // Collide test 186 // Collide test
@@ -225,8 +225,13 @@ namespace OpenSim.Region.PhysicsModule.ODE
225 /// <param name="req"></param> 225 /// <param name="req"></param>
226 private void RayCast(ODERayRequest req) 226 private void RayCast(ODERayRequest req)
227 { 227 {
228 // limit ray length or collisions will take all avaiable stack space
229 float len = req.length;
230 if (len > 250f)
231 len = 250f;
232
228 // Create the ray 233 // Create the ray
229 IntPtr ray = d.CreateRay(m_scene.space, req.length); 234 IntPtr ray = d.CreateRay(m_scene.space, len);
230 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); 235 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
231 236
232 // Collide test 237 // Collide test
@@ -438,4 +443,4 @@ namespace OpenSim.Region.PhysicsModule.ODE
438 public float length; 443 public float length;
439 public RayCallback callbackMethod; 444 public RayCallback callbackMethod;
440 } 445 }
441} \ No newline at end of file 446}
diff --git a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
index 8cc7f28..4e95b7a 100644
--- a/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/OdeScene.cs
@@ -40,6 +40,7 @@ using System.Diagnostics;
40using System.IO; 40using System.IO;
41using System.Linq; 41using System.Linq;
42using System.Reflection; 42using System.Reflection;
43using System.Runtime.ExceptionServices;
43using System.Runtime.InteropServices; 44using System.Runtime.InteropServices;
44using System.Threading; 45using System.Threading;
45using log4net; 46using log4net;
@@ -111,11 +112,9 @@ namespace OpenSim.Region.PhysicsModule.ODE
111 Rubber = 6 112 Rubber = 6
112 } 113 }
113 114
114 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ODEPhysicsScene")] 115 public class OdeScene : PhysicsScene
115 public class OdeScene : PhysicsScene, INonSharedRegionModule
116 { 116 {
117 private readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString()); 117 private readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString());
118 private bool m_Enabled = false;
119 118
120 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); 119 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
121 120
@@ -293,11 +292,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
293 292
294 private float contactsurfacelayer = 0.001f; 293 private float contactsurfacelayer = 0.001f;
295 294
296 private int worldHashspaceLow = -4; 295 private int HashspaceLow = -5;
297 private int worldHashspaceHigh = 128; 296 private int HashspaceHigh = 12;
298
299 private int smallHashspaceLow = -4;
300 private int smallHashspaceHigh = 66;
301 297
302 private float waterlevel = 0f; 298 private float waterlevel = 0f;
303 private int framecount = 0; 299 private int framecount = 0;
@@ -356,10 +352,6 @@ namespace OpenSim.Region.PhysicsModule.ODE
356 public float bodyPIDD = 35f; 352 public float bodyPIDD = 35f;
357 public float bodyPIDG = 25; 353 public float bodyPIDG = 25;
358 354
359 public int geomCrossingFailuresBeforeOutofbounds = 5;
360
361 public float bodyMotorJointMaxforceTensor = 2;
362
363 public int bodyFramesAutoDisable = 20; 355 public int bodyFramesAutoDisable = 20;
364 356
365 private float[] _watermap; 357 private float[] _watermap;
@@ -478,7 +470,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
478 private int m_physicsiterations = 10; 470 private int m_physicsiterations = 10;
479 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag 471 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
480 private readonly PhysicsActor PANull = new NullPhysicsActor(); 472 private readonly PhysicsActor PANull = new NullPhysicsActor();
481// private float step_time = 0.0f; 473 private float step_time = 0.0f;
482//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it 474//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it
483//Ckrinke private int ms = 0; 475//Ckrinke private int ms = 0;
484 public IntPtr world; 476 public IntPtr world;
@@ -534,89 +526,37 @@ namespace OpenSim.Region.PhysicsModule.ODE
534 int spaceGridMaxY; 526 int spaceGridMaxY;
535 527
536 private ODERayCastRequestManager m_rayCastManager; 528 private ODERayCastRequestManager m_rayCastManager;
529
530 public Scene m_frameWorkScene = null;
537 531
532 public OdeScene(Scene pscene, IConfigSource psourceconfig, string pname)
533 {
534 m_config = psourceconfig;
535 m_frameWorkScene = pscene;
536
537 EngineType = pname;
538 PhysicsSceneName = EngineType + "/" + pscene.RegionInfo.RegionName;
538 539
539 #region INonSharedRegionModule 540 pscene.RegisterModuleInterface<PhysicsScene>(this);
540 public string Name 541 Vector3 extent = new Vector3(pscene.RegionInfo.RegionSizeX, pscene.RegionInfo.RegionSizeY, pscene.RegionInfo.RegionSizeZ);
541 {
542 get { return "OpenDynamicsEngine"; }
543 }
544
545 public Type ReplaceableInterface
546 {
547 get { return null; }
548 }
549
550 public void Initialise(IConfigSource source)
551 {
552 // TODO: Move this out of Startup
553 IConfig config = source.Configs["Startup"];
554 if (config != null)
555 {
556 string physics = config.GetString("physics", string.Empty);
557 if (physics == Name)
558 {
559 m_Enabled = true;
560 m_config = source;
561
562 // We do this so that OpenSimulator on Windows loads the correct native ODE library depending on whether
563 // it's running as a 32-bit process or a 64-bit one. By invoking LoadLibary here, later DLLImports
564 // will find it already loaded later on.
565 //
566 // This isn't necessary for other platforms (e.g. Mac OSX and Linux) since the DLL used can be
567 // controlled in Ode.NET.dll.config
568 if (Util.IsWindows())
569 Util.LoadArchSpecificWindowsDll("ode.dll");
570
571 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
572 // http://opensimulator.org/mantis/view.php?id=2750).
573 d.InitODE();
574
575 }
576 }
577
578 }
579
580 public void Close()
581 {
582 }
583
584 public void AddRegion(Scene scene)
585 {
586 if (!m_Enabled)
587 return;
588
589 EngineType = Name;
590 PhysicsSceneName = EngineType + "/" + scene.RegionInfo.RegionName;
591
592 scene.RegisterModuleInterface<PhysicsScene>(this);
593 Vector3 extent = new Vector3(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY, scene.RegionInfo.RegionSizeZ);
594 Initialise(extent); 542 Initialise(extent);
595 InitialiseFromConfig(m_config); 543 InitialiseFromConfig(m_config);
596 544
597 // This may not be that good since terrain may not be avaiable at this point 545 // This may not be that good since terrain may not be avaiable at this point
598 base.Initialise(scene.PhysicsRequestAsset, 546 base.Initialise(pscene.PhysicsRequestAsset,
599 (scene.Heightmap != null ? scene.Heightmap.GetFloatsSerialised() : new float[(int)(extent.X * extent.Y)]), 547 (pscene.Heightmap != null ? pscene.Heightmap.GetFloatsSerialised() : new float[(int)(extent.X * extent.Y)]),
600 (float)scene.RegionInfo.RegionSettings.WaterHeight); 548 (float)pscene.RegionInfo.RegionSettings.WaterHeight);
601 549
602 } 550 }
603 551
604 public void RemoveRegion(Scene scene) 552 public void RegionLoaded()
605 { 553 {
606 if (!m_Enabled) 554 mesher = m_frameWorkScene.RequestModuleInterface<IMesher>();
607 return;
608 }
609
610 public void RegionLoaded(Scene scene)
611 {
612 if (!m_Enabled)
613 return;
614
615 mesher = scene.RequestModuleInterface<IMesher>();
616 if (mesher == null) 555 if (mesher == null)
617 m_log.WarnFormat("[ODE SCENE]: No mesher in {0}. Things will not work well.", PhysicsSceneName); 556 m_log.WarnFormat("[ODE SCENE]: No mesher in {0}. Things will not work well.", PhysicsSceneName);
557
558 m_frameWorkScene.PhysicsEnabled = true;
618 } 559 }
619 #endregion
620 560
621 /// <summary> 561 /// <summary>
622 /// Initiailizes the scene 562 /// Initiailizes the scene
@@ -633,8 +573,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
633 m_suportCombine = false; 573 m_suportCombine = false;
634 574
635 nearCallback = near; 575 nearCallback = near;
636 triCallback = TriCallback; 576// triCallback = TriCallback;
637 triArrayCallback = TriArrayCallback; 577// triArrayCallback = TriArrayCallback;
638 m_rayCastManager = new ODERayCastRequestManager(this); 578 m_rayCastManager = new ODERayCastRequestManager(this);
639 579
640 // Create the world and the first space 580 // Create the world and the first space
@@ -679,18 +619,9 @@ namespace OpenSim.Region.PhysicsModule.ODE
679 m_config = config; 619 m_config = config;
680 // Defaults 620 // Defaults
681 621
682 if (Environment.OSVersion.Platform == PlatformID.Unix) 622 avPIDD = 2200.0f;
683 { 623 avPIDP = 900.0f;
684 avPIDD = 3200.0f; 624 avStandupTensor = 550000f;
685 avPIDP = 1400.0f;
686 avStandupTensor = 2000000f;
687 }
688 else
689 {
690 avPIDD = 2200.0f;
691 avPIDP = 900.0f;
692 avStandupTensor = 550000f;
693 }
694 625
695 int contactsPerCollision = 80; 626 int contactsPerCollision = 80;
696 627
@@ -714,12 +645,10 @@ namespace OpenSim.Region.PhysicsModule.ODE
714 avatarTerminalVelocity, AvatarTerminalVelocity); 645 avatarTerminalVelocity, AvatarTerminalVelocity);
715 } 646 }
716 647
717 worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4); 648 HashspaceLow = physicsconfig.GetInt("world_hashspace_level_low", -5);
718 worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128); 649 HashspaceHigh = physicsconfig.GetInt("world_hashspace_level_high", 12);
719 650
720 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f); 651 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f);
721 smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4);
722 smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66);
723 652
724 contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f); 653 contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f);
725 654
@@ -738,7 +667,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
738 mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f); 667 mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f);
739 668
740 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE); 669 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE);
741 m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10); 670 m_physicsiterations = physicsconfig.GetInt("world_solver_iterations", 10);
742 671
743 avDensity = physicsconfig.GetFloat("av_density", 80f); 672 avDensity = physicsconfig.GetFloat("av_density", 80f);
744// avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f); 673// avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f);
@@ -754,7 +683,6 @@ namespace OpenSim.Region.PhysicsModule.ODE
754 683
755 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5); 684 geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 5);
756 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); 685 geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15);
757 geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5);
758 686
759 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f); 687 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f);
760 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20); 688 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20);
@@ -767,23 +695,10 @@ namespace OpenSim.Region.PhysicsModule.ODE
767 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); 695 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
768 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); 696 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
769 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); 697 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
770
771
772 698
773 if (Environment.OSVersion.Platform == PlatformID.Unix) 699 avPIDD = physicsconfig.GetFloat("av_pid_derivative", 2200.0f);
774 { 700 avPIDP = physicsconfig.GetFloat("av_pid_proportional", 900.0f);
775 avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f); 701 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor", 550000f);
776 avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f);
777 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f);
778 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f);
779 }
780 else
781 {
782 avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f);
783 avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f);
784 avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f);
785 bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f);
786 }
787 702
788 physics_logging = physicsconfig.GetBoolean("physics_logging", false); 703 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
789 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); 704 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
@@ -812,7 +727,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
812 if (spaceGridMaxY > 24) 727 if (spaceGridMaxY > 24)
813 { 728 {
814 spaceGridMaxY = 24; 729 spaceGridMaxY = 24;
815 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y ; 730 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y;
816 } 731 }
817 732
818 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY]; 733 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY];
@@ -984,7 +899,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
984 m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f; 899 m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f;
985 m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f; 900 m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f;
986 901
987 d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh); 902 d.HashSpaceSetLevels(space, HashspaceLow, HashspaceHigh);
988 903
989 // Set the gravity,, don't disable things automatically (we set it explicitly on some things) 904 // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
990 905
@@ -1864,10 +1779,10 @@ namespace OpenSim.Region.PhysicsModule.ODE
1864 //} 1779 //}
1865 // } 1780 // }
1866 } 1781 }
1867 1782/*
1868 private int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) 1783 private int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
1869 { 1784 {
1870 /* String name1 = null; 1785 String name1 = null;
1871 String name2 = null; 1786 String name2 = null;
1872 1787
1873 if (!geom_name_map.TryGetValue(trimesh, out name1)) 1788 if (!geom_name_map.TryGetValue(trimesh, out name1))
@@ -1880,7 +1795,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
1880 } 1795 }
1881 1796
1882 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); 1797 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
1883 */ 1798
1884 return 1; 1799 return 1;
1885 } 1800 }
1886 1801
@@ -1910,7 +1825,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
1910 1825
1911 return 1; 1826 return 1;
1912 } 1827 }
1913 1828*/
1914 /// <summary> 1829 /// <summary>
1915 /// This is our collision testing routine in ODE 1830 /// This is our collision testing routine in ODE
1916 /// </summary> 1831 /// </summary>
@@ -2042,7 +1957,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
2042 x = x - offsetX + 1f; 1957 x = x - offsetX + 1f;
2043 y = y - offsetY + 1f; 1958 y = y - offsetY + 1f;
2044 1959
2045 index = (int)((int)x * ((int)m_regionHeight +3) + (int)y); 1960 // map is rotated
1961 index = (int)x * ((int)m_regionHeight + 3) + (int)y;
2046 1962
2047 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length) 1963 if (index < TerrainHeightFieldHeights[heightFieldGeom].Length)
2048 { 1964 {
@@ -2620,59 +2536,13 @@ namespace OpenSim.Region.PhysicsModule.ODE
2620 2536
2621 2537
2622 } 2538 }
2623 // we don't want to remove the main space
2624
2625 // If the geometry is in the targetspace, remove it from the target space
2626 //m_log.Warn(prim.m_targetSpace);
2627
2628 //if (prim.m_targetSpace != IntPtr.Zero)
2629 //{
2630 //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom))
2631 //{
2632
2633 //if (d.GeomIsSpace(prim.m_targetSpace))
2634 //{
2635 //waitForSpaceUnlock(prim.m_targetSpace);
2636 //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom);
2637 prim.m_targetSpace = IntPtr.Zero; 2539 prim.m_targetSpace = IntPtr.Zero;
2638 //}
2639 //else
2640 //{
2641 // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2642 //((OdePrim)prim).m_targetSpace.ToString());
2643 //}
2644
2645 //}
2646 //}
2647 //m_log.Warn(prim.prim_geom);
2648
2649 if (!prim.RemoveGeom()) 2540 if (!prim.RemoveGeom())
2650 m_log.Warn("[ODE SCENE]: Unable to remove prim from physics scene"); 2541 m_log.Warn("[ODE SCENE]: Unable to remove prim from physics scene");
2651 2542
2652 lock (_prims) 2543 lock (_prims)
2653 _prims.Remove(prim); 2544 _prims.Remove(prim);
2654 2545
2655 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2656 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
2657 //{
2658 //if (prim.m_targetSpace != null)
2659 //{
2660 //if (d.GeomIsSpace(prim.m_targetSpace))
2661 //{
2662 //waitForSpaceUnlock(prim.m_targetSpace);
2663 //d.SpaceRemove(space, prim.m_targetSpace);
2664 // free up memory used by the space.
2665 //d.SpaceDestroy(prim.m_targetSpace);
2666 //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position);
2667 //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]);
2668 //}
2669 //else
2670 //{
2671 //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" +
2672 //((OdePrim) prim).m_targetSpace.ToString());
2673 //}
2674 //}
2675 //}
2676 2546
2677 if (SupportsNINJAJoints) 2547 if (SupportsNINJAJoints)
2678 RemoveAllJointsConnectedToActorThreadLocked(prim); 2548 RemoveAllJointsConnectedToActorThreadLocked(prim);
@@ -2768,12 +2638,9 @@ namespace OpenSim.Region.PhysicsModule.ODE
2768 { 2638 {
2769 if (d.GeomIsSpace(currentspace)) 2639 if (d.GeomIsSpace(currentspace))
2770 { 2640 {
2771// waitForSpaceUnlock(currentspace);
2772// waitForSpaceUnlock(space);
2773 d.SpaceRemove(space, currentspace); 2641 d.SpaceRemove(space, currentspace);
2774 // free up memory used by the space. 2642 // free up memory used by the space.
2775 2643
2776 //d.SpaceDestroy(currentspace);
2777 resetSpaceArrayItemToZero(currentspace); 2644 resetSpaceArrayItemToZero(currentspace);
2778 } 2645 }
2779 else 2646 else
@@ -2831,7 +2698,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
2831 if (newspace == IntPtr.Zero) 2698 if (newspace == IntPtr.Zero)
2832 { 2699 {
2833 newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); 2700 newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]);
2834 d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh); 2701 d.HashSpaceSetLevels(newspace, HashspaceLow, HashspaceHigh);
2835 } 2702 }
2836 2703
2837 return newspace; 2704 return newspace;
@@ -3052,6 +2919,46 @@ namespace OpenSim.Region.PhysicsModule.ODE
3052 } 2919 }
3053 } 2920 }
3054 2921
2922 // does all pending changes generated during region load process
2923 public override void ProcessPreSimulation()
2924 {
2925 lock (OdeLock)
2926 {
2927 if (world == IntPtr.Zero)
2928 {
2929 _taintedPrims.Clear();;
2930 return;
2931 }
2932
2933 int donechanges = 0;
2934 if (_taintedPrims.Count > 0)
2935 {
2936 m_log.InfoFormat("[Ode] start processing pending actor operations");
2937 int tstart = Util.EnvironmentTickCount();
2938
2939 lock (_taintedPrims)
2940 {
2941 foreach (OdePrim prim in _taintedPrims)
2942 {
2943 if (prim.m_taintremove)
2944 RemovePrimThreadLocked(prim);
2945 else
2946 prim.ProcessTaints();
2947
2948 prim.m_collisionscore = 0;
2949 donechanges++;
2950 }
2951 _taintedPrims.Clear();
2952 }
2953
2954 int time = Util.EnvironmentTickCountSubtract(tstart);
2955 m_log.InfoFormat("[Ode] finished {0} operations in {1}ms", donechanges, time);
2956 }
2957 m_log.InfoFormat("[Ode] {0} prim actors loaded",_prims.Count);
2958 }
2959 }
2960
2961
3055 /// <summary> 2962 /// <summary>
3056 /// This is our main simulate loop 2963 /// This is our main simulate loop
3057 /// </summary> 2964 /// </summary>
@@ -3077,26 +2984,12 @@ namespace OpenSim.Region.PhysicsModule.ODE
3077 2984
3078 float fps = 0; 2985 float fps = 0;
3079 2986
3080 float timeLeft = timeStep; 2987 step_time += timeStep;
2988
2989 float HalfOdeStep = ODE_STEPSIZE * 0.5f;
2990 if (step_time < HalfOdeStep)
2991 return 0;
3081 2992
3082 //m_log.Info(timeStep.ToString());
3083// step_time += timeSte
3084//
3085// // If We're loaded down by something else,
3086// // or debugging with the Visual Studio project on pause
3087// // skip a few frames to catch up gracefully.
3088// // without shooting the physicsactors all over the place
3089//
3090// if (step_time >= m_SkipFramesAtms)
3091// {
3092// // Instead of trying to catch up, it'll do 5 physics frames only
3093// step_time = ODE_STEPSIZE;
3094// m_physicsiterations = 5;
3095// }
3096// else
3097// {
3098// m_physicsiterations = 10;
3099// }
3100 2993
3101 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential 2994 // We change _collisionEventPrimChanges to avoid locking _collisionEventPrim itself and causing potential
3102 // deadlock if the collision event tries to lock something else later on which is already locked by a 2995 // deadlock if the collision event tries to lock something else later on which is already locked by a
@@ -3138,11 +3031,11 @@ namespace OpenSim.Region.PhysicsModule.ODE
3138 // Figure out the Frames Per Second we're going at. 3031 // Figure out the Frames Per Second we're going at.
3139 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size 3032 //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size
3140 3033
3141 fps = (timeStep / ODE_STEPSIZE) * 1000; 3034
3142 // HACK: Using a time dilation of 1.0 to debug rubberbanding issues 3035 // HACK: Using a time dilation of 1.0 to debug rubberbanding issues
3143 //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f); 3036 //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f);
3144 3037
3145 while (timeLeft > 0.0f) 3038 while (step_time > HalfOdeStep)
3146 { 3039 {
3147 try 3040 try
3148 { 3041 {
@@ -3307,7 +3200,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
3307 m_log.ErrorFormat("[ODE SCENE]: {0}, {1}, {2}", e.Message, e.TargetSite, e); 3200 m_log.ErrorFormat("[ODE SCENE]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
3308 } 3201 }
3309 3202
3310 timeLeft -= ODE_STEPSIZE; 3203 step_time -= ODE_STEPSIZE;
3204 fps += ODE_STEPSIZE;
3311 } 3205 }
3312 3206
3313 if (CollectStats) 3207 if (CollectStats)
@@ -3403,6 +3297,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
3403 m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick); 3297 m_stats[ODETotalFrameMsStatName] += Util.EnvironmentTickCountSubtract(startFrameTick);
3404 } 3298 }
3405 3299
3300 fps *= 1.0f/timeStep;
3406 return fps; 3301 return fps;
3407 } 3302 }
3408 3303
@@ -3675,7 +3570,6 @@ namespace OpenSim.Region.PhysicsModule.ODE
3675 3570
3676 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples]; 3571 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
3677 3572
3678
3679 const float scale = 1.0f; 3573 const float scale = 1.0f;
3680 const float offset = 0.0f; 3574 const float offset = 0.0f;
3681 const float thickness = 10f; 3575 const float thickness = 10f;
@@ -3740,7 +3634,8 @@ namespace OpenSim.Region.PhysicsModule.ODE
3740 IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); 3634 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3741 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, 3635 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0,
3742 heightmapWidth, heightmapHeight, 3636 heightmapWidth, heightmapHeight,
3743 (int)heightmapWidthSamples, (int)heightmapHeightSamples, 3637 (int)heightmapWidthSamples,
3638 (int)heightmapHeightSamples,
3744 scale, offset, thickness, wrap); 3639 scale, offset, thickness, wrap);
3745 3640
3746 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); 3641 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
@@ -3765,7 +3660,7 @@ namespace OpenSim.Region.PhysicsModule.ODE
3765 3660
3766 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); 3661 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle);
3767 d.GeomSetRotation(GroundGeom, ref R); 3662 d.GeomSetRotation(GroundGeom, ref R);
3768 d.GeomSetPosition(GroundGeom, pOffset.X + regionsizeX * 0.5f, pOffset.Y + regionsizeY * 0.5f, 0f); 3663 d.GeomSetPosition(GroundGeom, pOffset.X + regionsizeX * 0.5f, pOffset.Y + regionsizeY * 0.5f, 0.0f);
3769 IntPtr testGround = IntPtr.Zero; 3664 IntPtr testGround = IntPtr.Zero;
3770 if (RegionTerrain.TryGetValue(pOffset, out testGround)) 3665 if (RegionTerrain.TryGetValue(pOffset, out testGround))
3771 { 3666 {
@@ -3796,74 +3691,24 @@ namespace OpenSim.Region.PhysicsModule.ODE
3796 public override void SetWaterLevel(float baseheight) 3691 public override void SetWaterLevel(float baseheight)
3797 { 3692 {
3798 waterlevel = baseheight; 3693 waterlevel = baseheight;
3799// randomizeWater(waterlevel);
3800 } 3694 }
3801 3695
3802/* 3696 [HandleProcessCorruptedStateExceptions]
3803 private void randomizeWater(float baseheight) 3697 public override void Dispose()
3804 { 3698 {
3805 uint heightmapWidth = m_regionWidth + 2;
3806 uint heightmapHeight = m_regionHeight + 2;
3807 uint heightmapWidthSamples = m_regionWidth + 2;
3808 uint heightmapHeightSamples = m_regionHeight + 2;
3809 float scale = 1.0f;
3810 float offset = 0.0f;
3811 float thickness = 2.9f;
3812 int wrap = 0;
3813
3814 for (int i = 0; i < (258 * 258); i++)
3815 {
3816 _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f);
3817 // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f));
3818 }
3819
3820 lock (OdeLock) 3699 lock (OdeLock)
3821 { 3700 {
3822 if (WaterGeom != IntPtr.Zero) 3701 if(world == IntPtr.Zero)
3823 { 3702 return;
3824 d.SpaceRemove(space, WaterGeom);
3825 }
3826 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
3827 d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight,
3828 (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale,
3829 offset, thickness, wrap);
3830 d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight);
3831 WaterGeom = d.CreateHeightfield(space, HeightmapData, 1);
3832 if (WaterGeom != IntPtr.Zero)
3833 {
3834 d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water));
3835 d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space));
3836 }
3837
3838 geom_name_map[WaterGeom] = "Water";
3839
3840 d.Matrix3 R = new d.Matrix3();
3841
3842 Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f);
3843 Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f);
3844 //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1));
3845
3846 q1 = q1 * q2;
3847 //q1 = q1 * q3;
3848 Vector3 v3;
3849 float angle;
3850 q1.GetAxisAngle(out v3, out angle);
3851 3703
3852 d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); 3704 _worldInitialized = false;
3853 d.GeomSetRotation(WaterGeom, ref R);
3854 d.GeomSetPosition(WaterGeom, 128, 128, 0);
3855 }
3856 }
3857*/
3858 public override void Dispose()
3859 {
3860 _worldInitialized = false;
3861 3705
3862 m_rayCastManager.Dispose(); 3706 if (m_rayCastManager != null)
3863 m_rayCastManager = null; 3707 {
3708 m_rayCastManager.Dispose();
3709 m_rayCastManager = null;
3710 }
3864 3711
3865 lock (OdeLock)
3866 {
3867 lock (_prims) 3712 lock (_prims)
3868 { 3713 {
3869 foreach (OdePrim prm in _prims) 3714 foreach (OdePrim prm in _prims)
@@ -3876,10 +3721,29 @@ namespace OpenSim.Region.PhysicsModule.ODE
3876 //{ 3721 //{
3877 //RemoveAvatar(act); 3722 //RemoveAvatar(act);
3878 //} 3723 //}
3879 d.WorldDestroy(world); 3724 IntPtr GroundGeom = IntPtr.Zero;
3725 if (RegionTerrain.TryGetValue(m_worldOffset, out GroundGeom))
3726 {
3727 RegionTerrain.Remove(m_worldOffset);
3728 if (GroundGeom != IntPtr.Zero)
3729 {
3730 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
3731 TerrainHeightFieldHeights.Remove(GroundGeom);
3732 d.GeomDestroy(GroundGeom);
3733 }
3734 }
3735
3736 try
3737 {
3738 d.WorldDestroy(world);
3739 world = IntPtr.Zero;
3740 }
3741 catch (AccessViolationException e)
3742 {
3743 m_log.ErrorFormat("[ODE SCENE]: exception {0}", e.Message);
3744 }
3880 //d.CloseODE(); 3745 //d.CloseODE();
3881 } 3746 }
3882
3883 } 3747 }
3884 3748
3885 public override Dictionary<uint, float> GetTopColliders() 3749 public override Dictionary<uint, float> GetTopColliders()
diff --git a/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs b/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs
index 6dc22bd..2c134e7 100644
--- a/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs
+++ b/OpenSim/Region/PhysicsModules/Ode/Tests/ODETestClass.cs
@@ -47,6 +47,8 @@ namespace OpenSim.Region.PhysicsModule.ODE.Tests
47 47
48 //private OpenSim.Region.PhysicsModule.ODE.OdePlugin cbt; 48 //private OpenSim.Region.PhysicsModule.ODE.OdePlugin cbt;
49 private PhysicsScene pScene; 49 private PhysicsScene pScene;
50 private OpenSim.Region.PhysicsModule.ODE.OdeModule odemodule;
51
50 52
51 [SetUp] 53 [SetUp]
52 public void Initialize() 54 public void Initialize()
@@ -65,19 +67,18 @@ namespace OpenSim.Region.PhysicsModule.ODE.Tests
65 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize; 67 info.RegionSizeX = info.RegionSizeY = info.RegionSizeZ = Constants.RegionSize;
66 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info); 68 OpenSim.Region.Framework.Scenes.Scene scene = new OpenSim.Region.Framework.Scenes.Scene(info);
67 69
68 //IMesher mesher = new OpenSim.Region.PhysicsModules.Meshing.Meshmerizer(); 70 //IMesher mesher = new OpenSim.Region.PhysicsModule.Meshing.Meshmerizer();
69 //INonSharedRegionModule mod = mesher as INonSharedRegionModule; 71 //INonSharedRegionModule mod = mesher as INonSharedRegionModule;
70 //mod.Initialise(openSimINI); 72 //mod.Initialise(openSimINI);
71 //mod.AddRegion(scene); 73 //mod.AddRegion(scene);
72 //mod.RegionLoaded(scene); 74 //mod.RegionLoaded(scene);
73 75
74 pScene = new OdeScene(); 76 // pScene = new OdeScene();
75 Console.WriteLine("HERE " + (pScene == null ? "Null" : "Not null")); 77 odemodule = new OpenSim.Region.PhysicsModule.ODE.OdeModule();
76 INonSharedRegionModule mod = (pScene as INonSharedRegionModule); 78 Console.WriteLine("HERE " + (odemodule == null ? "Null" : "Not null"));
77 Console.WriteLine("HERE " + (mod == null ? "Null" : "Not null")); 79 odemodule.Initialise(openSimINI);
78 mod.Initialise(openSimINI); 80 odemodule.AddRegion(scene);
79 mod.AddRegion(scene); 81 odemodule.RegionLoaded(scene);
80 mod.RegionLoaded(scene);
81 82
82 // Loading ODEPlugin 83 // Loading ODEPlugin
83 //cbt = new OdePlugin(); 84 //cbt = new OdePlugin();
@@ -90,6 +91,7 @@ namespace OpenSim.Region.PhysicsModule.ODE.Tests
90 { 91 {
91 _heightmap[i] = 21f; 92 _heightmap[i] = 21f;
92 } 93 }
94 pScene = scene.PhysicsScene;
93 pScene.SetTerrain(_heightmap); 95 pScene.SetTerrain(_heightmap);
94 } 96 }
95 97
diff --git a/OpenSim/Region/PhysicsModules/POS/POSCharacter.cs b/OpenSim/Region/PhysicsModules/POS/POSCharacter.cs
index 32469d9..28d2b53 100644
--- a/OpenSim/Region/PhysicsModules/POS/POSCharacter.cs
+++ b/OpenSim/Region/PhysicsModules/POS/POSCharacter.cs
@@ -248,7 +248,7 @@ namespace OpenSim.Region.PhysicsModule.POS
248 { 248 {
249 } 249 }
250 250
251 public override void LockAngularMotion(Vector3 axis) 251 public override void LockAngularMotion(byte axislocks)
252 { 252 {
253 } 253 }
254 254
@@ -291,6 +291,7 @@ namespace OpenSim.Region.PhysicsModule.POS
291 291
292 public override bool PIDHoverActive 292 public override bool PIDHoverActive
293 { 293 {
294 get { return false; }
294 set { return; } 295 set { return; }
295 } 296 }
296 297
diff --git a/OpenSim/Region/PhysicsModules/POS/POSPrim.cs b/OpenSim/Region/PhysicsModules/POS/POSPrim.cs
index 8aae716..180885d 100644
--- a/OpenSim/Region/PhysicsModules/POS/POSPrim.cs
+++ b/OpenSim/Region/PhysicsModules/POS/POSPrim.cs
@@ -250,7 +250,7 @@ namespace OpenSim.Region.PhysicsModule.POS
250 { 250 {
251 } 251 }
252 252
253 public override void LockAngularMotion(Vector3 axis) 253 public override void LockAngularMotion(byte axislocks)
254 { 254 {
255 } 255 }
256 256
@@ -286,6 +286,7 @@ namespace OpenSim.Region.PhysicsModule.POS
286 286
287 public override bool PIDHoverActive 287 public override bool PIDHoverActive
288 { 288 {
289 get { return false; }
289 set { return; } 290 set { return; }
290 } 291 }
291 292
@@ -298,7 +299,7 @@ namespace OpenSim.Region.PhysicsModule.POS
298 { 299 {
299 set { return; } 300 set { return; }
300 } 301 }
301 302
302 public override Quaternion APIDTarget 303 public override Quaternion APIDTarget
303 { 304 {
304 set { return; } 305 set { return; }
diff --git a/OpenSim/Region/PhysicsModules/POS/POSScene.cs b/OpenSim/Region/PhysicsModules/POS/POSScene.cs
index 6375f18..e6bcbf2 100644
--- a/OpenSim/Region/PhysicsModules/POS/POSScene.cs
+++ b/OpenSim/Region/PhysicsModules/POS/POSScene.cs
@@ -288,7 +288,7 @@ namespace OpenSim.Region.PhysicsModule.POS
288 character._velocity.Z = (character.Position.Z - oldposZ)/timeStep; 288 character._velocity.Z = (character.Position.Z - oldposZ)/timeStep;
289 } 289 }
290 } 290 }
291 return fps; 291 return 1.0f;
292 } 292 }
293 293
294 public override void GetResults() 294 public override void GetResults()
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs b/OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs
index 5c75307..88169bb 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/IMesher.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Runtime.InteropServices;
30using OpenSim.Framework; 31using OpenSim.Framework;
31using OpenMetaverse; 32using OpenMetaverse;
32 33
@@ -36,7 +37,12 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
36 { 37 {
37 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod); 38 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod);
38 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical); 39 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical);
39 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache); 40 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde);
41 IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde);
42 IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex);
43 void ReleaseMesh(IMesh mesh);
44 void ExpireReleaseMeshs();
45 void ExpireFileCache();
40 } 46 }
41 47
42 // Values for level of detail to be passed to the mesher. 48 // Values for level of detail to be passed to the mesher.
@@ -54,6 +60,25 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
54 { 60 {
55 } 61 }
56 62
63 [Serializable()]
64 [StructLayout(LayoutKind.Explicit)]
65 public struct AMeshKey
66 {
67 [FieldOffset(0)]
68 public UUID uuid;
69 [FieldOffset(0)]
70 public ulong hashA;
71 [FieldOffset(8)]
72 public ulong hashB;
73 [FieldOffset(16)]
74 public ulong hashC;
75
76 public override string ToString()
77 {
78 return uuid.ToString() + "-" + hashC.ToString("x") ;
79 }
80 }
81
57 public interface IMesh 82 public interface IMesh
58 { 83 {
59 List<Vector3> getVertexList(); 84 List<Vector3> getVertexList();
@@ -67,5 +92,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
67 void releasePinned(); 92 void releasePinned();
68 void Append(IMesh newMesh); 93 void Append(IMesh newMesh);
69 void TransformLinear(float[,] matrix, float[] offset); 94 void TransformLinear(float[,] matrix, float[] offset);
95 Vector3 GetCentroid();
96 Vector3 GetOBB();
70 } 97 }
71} 98}
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
index c04ff58..ebd2185 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
@@ -43,7 +43,8 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
43 Unknown = 0, 43 Unknown = 0,
44 Agent = 1, 44 Agent = 1,
45 Prim = 2, 45 Prim = 2,
46 Ground = 3 46 Ground = 3,
47 Water = 4
47 } 48 }
48 49
49 public enum PIDHoverType 50 public enum PIDHoverType
@@ -59,15 +60,41 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
59 public Vector3 Position; 60 public Vector3 Position;
60 public Vector3 SurfaceNormal; 61 public Vector3 SurfaceNormal;
61 public float PenetrationDepth; 62 public float PenetrationDepth;
63 public float RelativeSpeed;
64 public bool CharacterFeet;
62 65
63 public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth) 66 public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth)
64 { 67 {
65 Position = position; 68 Position = position;
66 SurfaceNormal = surfaceNormal; 69 SurfaceNormal = surfaceNormal;
67 PenetrationDepth = penetrationDepth; 70 PenetrationDepth = penetrationDepth;
71 RelativeSpeed = 0f; // for now let this one be set explicity
72 CharacterFeet = true; // keep other plugins work as before
73 }
74
75 public ContactPoint(Vector3 position, Vector3 surfaceNormal, float penetrationDepth, bool feet)
76 {
77 Position = position;
78 SurfaceNormal = surfaceNormal;
79 PenetrationDepth = penetrationDepth;
80 RelativeSpeed = 0f; // for now let this one be set explicity
81 CharacterFeet = feet; // keep other plugins work as before
68 } 82 }
69 } 83 }
70 84
85 public struct ContactData
86 {
87 public float mu;
88 public float bounce;
89 public bool softcolide;
90
91 public ContactData(float _mu, float _bounce, bool _softcolide)
92 {
93 mu = _mu;
94 bounce = _bounce;
95 softcolide = _softcolide;
96 }
97 }
71 /// <summary> 98 /// <summary>
72 /// Used to pass collision information to OnCollisionUpdate listeners. 99 /// Used to pass collision information to OnCollisionUpdate listeners.
73 /// </summary> 100 /// </summary>
@@ -99,7 +126,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
99 m_objCollisionList.Add(localID, contact); 126 m_objCollisionList.Add(localID, contact);
100 } 127 }
101 else 128 else
102 { 129 {
103 if (m_objCollisionList[localID].PenetrationDepth < contact.PenetrationDepth) 130 if (m_objCollisionList[localID].PenetrationDepth < contact.PenetrationDepth)
104 m_objCollisionList[localID] = contact; 131 m_objCollisionList[localID] = contact;
105 } 132 }
@@ -142,11 +169,32 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
142 { 169 {
143 get { return new NullPhysicsActor(); } 170 get { return new NullPhysicsActor(); }
144 } 171 }
172
173 public virtual bool Building { get; set; }
174
175 public virtual void getContactData(ref ContactData cdata)
176 {
177 cdata.mu = 0;
178 cdata.bounce = 0;
179 }
145 180
146 public abstract bool Stopped { get; } 181 public abstract bool Stopped { get; }
147 182
148 public abstract Vector3 Size { get; set; } 183 public abstract Vector3 Size { get; set; }
149 184
185 public virtual void setAvatarSize(Vector3 size, float feetOffset)
186 {
187 Size = size;
188 }
189
190 public virtual bool Phantom { get; set; }
191
192 public virtual bool IsVolumeDtc
193 {
194 get { return false; }
195 set { return; }
196 }
197
150 public virtual byte PhysicsShapeType { get; set; } 198 public virtual byte PhysicsShapeType { get; set; }
151 199
152 public abstract PrimitiveBaseShape Shape { set; } 200 public abstract PrimitiveBaseShape Shape { set; }
@@ -169,7 +217,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
169 /// XXX: Bizarrely, this cannot be "Terrain" or "Water" right now unless it really is simulating terrain or 217 /// XXX: Bizarrely, this cannot be "Terrain" or "Water" right now unless it really is simulating terrain or
170 /// water. This is not a problem due to the formatting of names given by prims and avatars. 218 /// water. This is not a problem due to the formatting of names given by prims and avatars.
171 /// </remarks> 219 /// </remarks>
172 public string Name { get; protected set; } 220 public string Name { get; set; }
173 221
174 /// <summary> 222 /// <summary>
175 /// This is being used by ODE joint code. 223 /// This is being used by ODE joint code.
@@ -182,8 +230,8 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
182 230
183 public abstract void delink(); 231 public abstract void delink();
184 232
185 public abstract void LockAngularMotion(Vector3 axis); 233 public abstract void LockAngularMotion(byte axislocks);
186 234
187 public virtual void RequestPhysicsterseUpdate() 235 public virtual void RequestPhysicsterseUpdate()
188 { 236 {
189 // Make a temporary copy of the event to avoid possibility of 237 // Make a temporary copy of the event to avoid possibility of
@@ -245,6 +293,56 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
245 public abstract void VehicleRotationParam(int param, Quaternion rotation); 293 public abstract void VehicleRotationParam(int param, Quaternion rotation);
246 public abstract void VehicleFlags(int param, bool remove); 294 public abstract void VehicleFlags(int param, bool remove);
247 295
296 // This is an overridable version of SetVehicle() that works for all physics engines.
297 // This is VERY inefficient. It behoves any physics engine to override this and
298 // implement a more efficient setting of all the vehicle parameters.
299 public virtual void SetVehicle(object pvdata)
300 {
301 VehicleData vdata = (VehicleData)pvdata;
302 // vehicleActor.ProcessSetVehicle((VehicleData)vdata);
303
304 this.VehicleType = (int)vdata.m_type;
305 this.VehicleFlags(-1, false); // clears all flags
306 this.VehicleFlags((int)vdata.m_flags, false);
307
308 // Linear properties
309 this.VehicleVectorParam((int)Vehicle.LINEAR_MOTOR_DIRECTION, vdata.m_linearMotorDirection);
310 this.VehicleVectorParam((int)Vehicle.LINEAR_FRICTION_TIMESCALE, vdata.m_linearFrictionTimescale);
311 this.VehicleFloatParam((int)Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE, vdata.m_linearMotorDecayTimescale);
312 this.VehicleFloatParam((int)Vehicle.LINEAR_MOTOR_TIMESCALE, vdata.m_linearMotorTimescale);
313 this.VehicleVectorParam((int)Vehicle.LINEAR_MOTOR_OFFSET, vdata.m_linearMotorOffset);
314
315 //Angular properties
316 this.VehicleVectorParam((int)Vehicle.ANGULAR_MOTOR_DIRECTION, vdata.m_angularMotorDirection);
317 this.VehicleFloatParam((int)Vehicle.ANGULAR_MOTOR_TIMESCALE, vdata.m_angularMotorTimescale);
318 this.VehicleFloatParam((int)Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE, vdata.m_angularMotorDecayTimescale);
319 this.VehicleVectorParam((int)Vehicle.ANGULAR_FRICTION_TIMESCALE, vdata.m_angularFrictionTimescale);
320
321 //Deflection properties
322 this.VehicleFloatParam((int)Vehicle.ANGULAR_DEFLECTION_EFFICIENCY, vdata.m_angularDeflectionEfficiency);
323 this.VehicleFloatParam((int)Vehicle.ANGULAR_DEFLECTION_TIMESCALE, vdata.m_angularDeflectionTimescale);
324 this.VehicleFloatParam((int)Vehicle.LINEAR_DEFLECTION_EFFICIENCY, vdata.m_linearDeflectionEfficiency);
325 this.VehicleFloatParam((int)Vehicle.LINEAR_DEFLECTION_TIMESCALE, vdata.m_linearDeflectionTimescale);
326
327 //Banking properties
328 this.VehicleFloatParam((int)Vehicle.BANKING_EFFICIENCY, vdata.m_bankingEfficiency);
329 this.VehicleFloatParam((int)Vehicle.BANKING_MIX, vdata.m_bankingMix);
330 this.VehicleFloatParam((int)Vehicle.BANKING_TIMESCALE, vdata.m_bankingTimescale);
331
332 //Hover and Buoyancy properties
333 this.VehicleFloatParam((int)Vehicle.HOVER_HEIGHT, vdata.m_VhoverHeight);
334 this.VehicleFloatParam((int)Vehicle.HOVER_EFFICIENCY, vdata.m_VhoverEfficiency);
335 this.VehicleFloatParam((int)Vehicle.HOVER_TIMESCALE, vdata.m_VhoverTimescale);
336 this.VehicleFloatParam((int)Vehicle.BUOYANCY, vdata.m_VehicleBuoyancy);
337
338 //Attractor properties
339 this.VehicleFloatParam((int)Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, vdata.m_verticalAttractionEfficiency);
340 this.VehicleFloatParam((int)Vehicle.VERTICAL_ATTRACTION_TIMESCALE, vdata.m_verticalAttractionTimescale);
341
342 this.VehicleRotationParam((int)Vehicle.REFERENCE_FRAME, vdata.m_referenceFrame);
343 }
344
345
248 /// <summary> 346 /// <summary>
249 /// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 347 /// Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
250 /// </summary> 348 /// </summary>
@@ -253,6 +351,51 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
253 public abstract Vector3 GeometricCenter { get; } 351 public abstract Vector3 GeometricCenter { get; }
254 public abstract Vector3 CenterOfMass { get; } 352 public abstract Vector3 CenterOfMass { get; }
255 353
354 public virtual Vector3 OOBsize
355 {
356 get
357 {
358 Vector3 s=Size;
359 s.X *=0.5f;
360 s.Y *=0.5f;
361 s.Z *=0.5f;
362 return s;
363 }
364 }
365
366 public virtual Vector3 OOBoffset
367 {
368 get
369 {
370 return Vector3.Zero;
371 }
372 }
373
374 public virtual float OOBRadiusSQ
375 {
376 get
377 {
378 return Size.LengthSquared() * 0.25f; // ((0.5^2)
379 }
380 }
381
382
383 public virtual float PhysicsCost
384 {
385 get
386 {
387 return 0.1f;
388 }
389 }
390
391 public virtual float StreamCost
392 {
393 get
394 {
395 return 1.0f;
396 }
397 }
398
256 /// <summary> 399 /// <summary>
257 /// The desired velocity of this actor. 400 /// The desired velocity of this actor.
258 /// </summary> 401 /// </summary>
@@ -296,7 +439,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
296 439
297 // Used for llSetHoverHeight and maybe vehicle height 440 // Used for llSetHoverHeight and maybe vehicle height
298 // Hover Height will override MoveTo target's Z 441 // Hover Height will override MoveTo target's Z
299 public abstract bool PIDHoverActive { set;} 442 public abstract bool PIDHoverActive {get; set;}
300 public abstract float PIDHoverHeight { set;} 443 public abstract float PIDHoverHeight { set;}
301 public abstract PIDHoverType PIDHoverType { set;} 444 public abstract PIDHoverType PIDHoverType { set;}
302 public abstract float PIDHoverTau { set;} 445 public abstract float PIDHoverTau { set;}
@@ -314,6 +457,12 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
314 public abstract void UnSubscribeEvents(); 457 public abstract void UnSubscribeEvents();
315 public abstract bool SubscribedEvents(); 458 public abstract bool SubscribedEvents();
316 459
460 public virtual void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { }
461
462 // Warning in a parent part it returns itself, not null
463 public virtual PhysicsActor ParentActor { get { return this; } }
464
465
317 // Extendable interface for new, physics engine specific operations 466 // Extendable interface for new, physics engine specific operations
318 public virtual object Extension(string pFunct, params object[] pParams) 467 public virtual object Extension(string pFunct, params object[] pParams)
319 { 468 {
@@ -324,9 +473,11 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
324 473
325 public class NullPhysicsActor : PhysicsActor 474 public class NullPhysicsActor : PhysicsActor
326 { 475 {
476 private ActorTypes m_actorType = ActorTypes.Unknown;
477
327 public override bool Stopped 478 public override bool Stopped
328 { 479 {
329 get{ return false; } 480 get{ return true; }
330 } 481 }
331 482
332 public override Vector3 Position 483 public override Vector3 Position
@@ -343,6 +494,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
343 494
344 public override uint LocalID 495 public override uint LocalID
345 { 496 {
497 get { return 0; }
346 set { return; } 498 set { return; }
347 } 499 }
348 500
@@ -402,50 +554,17 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
402 set { return; } 554 set { return; }
403 } 555 }
404 556
405 public override void VehicleFloatParam(int param, float value) 557 public override void VehicleFloatParam(int param, float value) {}
406 { 558 public override void VehicleVectorParam(int param, Vector3 value) { }
407 559 public override void VehicleRotationParam(int param, Quaternion rotation) { }
408 } 560 public override void VehicleFlags(int param, bool remove) { }
409 561 public override void SetVolumeDetect(int param) {}
410 public override void VehicleVectorParam(int param, Vector3 value) 562 public override void SetMaterial(int material) {}
411 { 563 public override Vector3 CenterOfMass { get { return Vector3.Zero; }}
412
413 }
414
415 public override void VehicleRotationParam(int param, Quaternion rotation)
416 {
417
418 }
419 564
420 public override void VehicleFlags(int param, bool remove) 565 public override Vector3 GeometricCenter { get { return Vector3.Zero; }}
421 {
422
423 }
424
425 public override void SetVolumeDetect(int param)
426 {
427
428 }
429
430 public override void SetMaterial(int material)
431 {
432
433 }
434
435 public override Vector3 CenterOfMass
436 {
437 get { return Vector3.Zero; }
438 }
439
440 public override Vector3 GeometricCenter
441 {
442 get { return Vector3.Zero; }
443 }
444 566
445 public override PrimitiveBaseShape Shape 567 public override PrimitiveBaseShape Shape { set { return; }}
446 {
447 set { return; }
448 }
449 568
450 public override Vector3 Velocity 569 public override Vector3 Velocity
451 { 570 {
@@ -465,9 +584,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
465 set { } 584 set { }
466 } 585 }
467 586
468 public override void CrossingFailure() 587 public override void CrossingFailure() {}
469 {
470 }
471 588
472 public override Quaternion Orientation 589 public override Quaternion Orientation
473 { 590 {
@@ -507,8 +624,20 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
507 624
508 public override int PhysicsActorType 625 public override int PhysicsActorType
509 { 626 {
510 get { return (int) ActorTypes.Unknown; } 627 get { return (int)m_actorType; }
511 set { return; } 628 set {
629 ActorTypes type = (ActorTypes)value;
630 switch (type)
631 {
632 case ActorTypes.Ground:
633 case ActorTypes.Water:
634 m_actorType = type;
635 break;
636 default:
637 m_actorType = ActorTypes.Unknown;
638 break;
639 }
640 }
512 } 641 }
513 642
514 public override bool Kinematic 643 public override bool Kinematic
@@ -517,26 +646,11 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
517 set { return; } 646 set { return; }
518 } 647 }
519 648
520 public override void link(PhysicsActor obj) 649 public override void link(PhysicsActor obj) { }
521 { 650 public override void delink() { }
522 } 651 public override void LockAngularMotion(byte axislocks) { }
523 652 public override void AddForce(Vector3 force, bool pushforce) { }
524 public override void delink() 653 public override void AddAngularForce(Vector3 force, bool pushforce) { }
525 {
526 }
527
528 public override void LockAngularMotion(Vector3 axis)
529 {
530 }
531
532 public override void AddForce(Vector3 force, bool pushforce)
533 {
534 }
535
536 public override void AddAngularForce(Vector3 force, bool pushforce)
537 {
538
539 }
540 654
541 public override Vector3 RotationalVelocity 655 public override Vector3 RotationalVelocity
542 { 656 {
@@ -555,7 +669,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
555 public override float PIDTau { set { return; } } 669 public override float PIDTau { set { return; } }
556 670
557 public override float PIDHoverHeight { set { return; } } 671 public override float PIDHoverHeight { set { return; } }
558 public override bool PIDHoverActive { set { return; } } 672 public override bool PIDHoverActive {get {return false;} set { return; } }
559 public override PIDHoverType PIDHoverType { set { return; } } 673 public override PIDHoverType PIDHoverType { set { return; } }
560 public override float PIDHoverTau { set { return; } } 674 public override float PIDHoverTau { set { return; } }
561 675
@@ -564,21 +678,10 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
564 public override float APIDStrength { set { return; } } 678 public override float APIDStrength { set { return; } }
565 public override float APIDDamping { set { return; } } 679 public override float APIDDamping { set { return; } }
566 680
567 public override void SetMomentum(Vector3 momentum) 681 public override void SetMomentum(Vector3 momentum) { }
568 {
569 }
570 682
571 public override void SubscribeEvents(int ms) 683 public override void SubscribeEvents(int ms) { }
572 { 684 public override void UnSubscribeEvents() { }
573 685 public override bool SubscribedEvents() { return false; }
574 }
575 public override void UnSubscribeEvents()
576 {
577
578 }
579 public override bool SubscribedEvents()
580 {
581 return false;
582 }
583 } 686 }
584} 687}
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs
index 32691fc..8623891 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsScene.cs
@@ -41,6 +41,10 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
41 41
42 public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal); 42 public delegate void RaycastCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal);
43 public delegate void RayCallback(List<ContactResult> list); 43 public delegate void RayCallback(List<ContactResult> list);
44 public delegate void ProbeBoxCallback(List<ContactResult> list);
45 public delegate void ProbeSphereCallback(List<ContactResult> list);
46 public delegate void ProbePlaneCallback(List<ContactResult> list);
47 public delegate void SitAvatarCallback(int status, uint partID, Vector3 offset, Quaternion Orientation);
44 48
45 public delegate void JointMoved(PhysicsJoint joint); 49 public delegate void JointMoved(PhysicsJoint joint);
46 public delegate void JointDeactivated(PhysicsJoint joint); 50 public delegate void JointDeactivated(PhysicsJoint joint);
@@ -89,6 +93,8 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
89 public Vector3 Normal; 93 public Vector3 Normal;
90 } 94 }
91 95
96
97
92 public abstract class PhysicsScene 98 public abstract class PhysicsScene
93 { 99 {
94// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 100// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -143,6 +149,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
143 /// <param name="size"></param> 149 /// <param name="size"></param>
144 /// <param name="isFlying"></param> 150 /// <param name="isFlying"></param>
145 /// <returns></returns> 151 /// <returns></returns>
152
146 public abstract PhysicsActor AddAvatar( 153 public abstract PhysicsActor AddAvatar(
147 string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying); 154 string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying);
148 155
@@ -161,12 +168,26 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
161 { 168 {
162 PhysicsActor ret = AddAvatar(avName, position, velocity, size, isFlying); 169 PhysicsActor ret = AddAvatar(avName, position, velocity, size, isFlying);
163 170
164 if (ret != null) 171 if (ret != null)
165 ret.LocalID = localID; 172 ret.LocalID = localID;
166 173
167 return ret; 174 return ret;
168 } 175 }
169 176
177 public virtual PhysicsActor AddAvatar(
178 uint localID, string avName, Vector3 position, Vector3 size, bool isFlying)
179 {
180 PhysicsActor ret = AddAvatar(localID, avName, position, Vector3.Zero, size, isFlying);
181 return ret;
182 }
183
184 public virtual PhysicsActor AddAvatar(
185 uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying)
186 {
187 PhysicsActor ret = AddAvatar(localID, avName, position, Vector3.Zero, size, isFlying);
188 return ret;
189 }
190
170 /// <summary> 191 /// <summary>
171 /// Remove an avatar. 192 /// Remove an avatar.
172 /// </summary> 193 /// </summary>
@@ -182,6 +203,19 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
182 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 203 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
183 Vector3 size, Quaternion rotation, bool isPhysical, uint localid); 204 Vector3 size, Quaternion rotation, bool isPhysical, uint localid);
184 205
206 public virtual PhysicsActor AddPrimShape(string primName, PhysicsActor parent, PrimitiveBaseShape pbs, Vector3 position,
207 uint localid, byte[] sdata)
208 {
209 return null;
210 }
211
212 public virtual PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
213 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
214 {
215 return AddPrimShape(primName, pbs, position, size, rotation, isPhysical, localid);
216 }
217
218
185 public virtual PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 219 public virtual PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
186 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapetype, uint localid) 220 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapetype, uint localid)
187 { 221 {
@@ -255,6 +289,9 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
255 289
256 public abstract void AddPhysicsActorTaint(PhysicsActor prim); 290 public abstract void AddPhysicsActorTaint(PhysicsActor prim);
257 291
292
293 public virtual void ProcessPreSimulation() { }
294
258 /// <summary> 295 /// <summary>
259 /// Perform a simulation of the current physics scene over the given timestep. 296 /// Perform a simulation of the current physics scene over the given timestep.
260 /// </summary> 297 /// </summary>
@@ -299,7 +336,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
299 } 336 }
300 337
301 public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {} 338 public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {}
302 339 public virtual void CombineTerrain(float[] heightMap, Vector3 pOffset) {}
303 public virtual void UnCombine(PhysicsScene pScene) {} 340 public virtual void UnCombine(PhysicsScene pScene) {}
304 341
305 /// <summary> 342 /// <summary>
@@ -348,6 +385,31 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
348 return false; 385 return false;
349 } 386 }
350 387
388 public virtual List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
389 {
390 return new List<ContactResult>();
391 }
392
393 public virtual List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
394 {
395 return new List<ContactResult>();
396 }
397
398 public virtual List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
399 {
400 return new List<ContactResult>();
401 }
402
403 public virtual List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
404 {
405 return new List<ContactResult>();
406 }
407
408 public virtual int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)
409 {
410 return 0;
411 }
412
351 // Extendable interface for new, physics engine specific operations 413 // Extendable interface for new, physics engine specific operations
352 public virtual object Extension(string pFunct, params object[] pParams) 414 public virtual object Extension(string pFunct, params object[] pParams)
353 { 415 {
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs b/OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs
index 63a8cb8..e850b11 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/VehicleConstants.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse;
29 30
30namespace OpenSim.Region.PhysicsModules.SharedBase 31namespace OpenSim.Region.PhysicsModules.SharedBase
31{ 32{
@@ -117,5 +118,47 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
117 NO_DEFLECTION = 16392, 118 NO_DEFLECTION = 16392,
118 LOCK_ROTATION = 32784 119 LOCK_ROTATION = 32784
119 } 120 }
120 121
122 public struct VehicleData
123 {
124 public Vehicle m_type;
125 public VehicleFlag m_flags;
126
127 // Linear properties
128 public Vector3 m_linearMotorDirection;
129 public Vector3 m_linearFrictionTimescale;
130 public float m_linearMotorDecayTimescale;
131 public float m_linearMotorTimescale;
132 public Vector3 m_linearMotorOffset;
133
134 //Angular properties
135 public Vector3 m_angularMotorDirection;
136 public float m_angularMotorTimescale;
137 public float m_angularMotorDecayTimescale;
138 public Vector3 m_angularFrictionTimescale;
139
140 //Deflection properties
141 public float m_angularDeflectionEfficiency;
142 public float m_angularDeflectionTimescale;
143 public float m_linearDeflectionEfficiency;
144 public float m_linearDeflectionTimescale;
145
146 //Banking properties
147 public float m_bankingEfficiency;
148 public float m_bankingMix;
149 public float m_bankingTimescale;
150
151 //Hover and Buoyancy properties
152 public float m_VhoverHeight;
153 public float m_VhoverEfficiency;
154 public float m_VhoverTimescale;
155 public float m_VehicleBuoyancy;
156
157 //Attractor properties
158 public float m_verticalAttractionEfficiency;
159 public float m_verticalAttractionTimescale;
160
161 // Axis
162 public Quaternion m_referenceFrame;
163 }
121} 164}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs
new file mode 100644
index 0000000..daf3af1
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEApi.cs
@@ -0,0 +1,2024 @@
1/*
2 * based on:
3 * Ode.NET - .NET bindings for ODE
4 * Jason Perkins (starkos@industriousone.com)
5 * Licensed under the New BSD
6 * Part of the OpenDynamicsEngine
7Open Dynamics Engine
8Copyright (c) 2001-2007, Russell L. Smith.
9All rights reserved.
10
11Redistribution and use in source and binary forms, with or without
12modification, are permitted provided that the following conditions
13are met:
14
15Redistributions of source code must retain the above copyright notice,
16this list of conditions and the following disclaimer.
17
18Redistributions in binary form must reproduce the above copyright notice,
19this list of conditions and the following disclaimer in the documentation
20and/or other materials provided with the distribution.
21
22Neither the names of ODE's copyright owner nor the names of its
23contributors may be used to endorse or promote products derived from
24this software without specific prior written permission.
25
26THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 *
38 * changes by opensim team;
39 * changes by Aurora team http://www.aurora-sim.org/
40 * changes by Ubit Umarov
41 */
42
43using System;
44using System.Runtime.InteropServices;
45using System.Security;
46using OMV = OpenMetaverse;
47namespace OdeAPI
48{
49//#if dDOUBLE
50// don't see much use in double precision with time steps of 20ms and 10 iterations used on opensim
51// at least we save same memory and memory access time, FPU performance on intel usually is similar
52// using dReal = System.Double;
53//#else
54 using dReal = System.Single;
55//#endif
56
57 public static class d
58 {
59 public static dReal Infinity = dReal.MaxValue;
60 public static int NTotalBodies = 0;
61 public static int NTotalGeoms = 0;
62
63 public const uint CONTACTS_UNIMPORTANT = 0x80000000;
64
65 #region Flags and Enumerations
66
67 [Flags]
68 public enum AllocateODEDataFlags : uint
69 {
70 BasicData = 0,
71 CollisionData = 0x00000001,
72 All = ~0u
73 }
74
75 [Flags]
76 public enum IniteODEFlags : uint
77 {
78 dInitFlagManualThreadCleanup = 0x00000001
79 }
80
81 [Flags]
82 public enum ContactFlags : int
83 {
84 Mu2 = 0x001,
85 FDir1 = 0x002,
86 Bounce = 0x004,
87 SoftERP = 0x008,
88 SoftCFM = 0x010,
89 Motion1 = 0x020,
90 Motion2 = 0x040,
91 MotionN = 0x080,
92 Slip1 = 0x100,
93 Slip2 = 0x200,
94 Approx0 = 0x0000,
95 Approx1_1 = 0x1000,
96 Approx1_2 = 0x2000,
97 Approx1 = 0x3000
98 }
99
100 public enum GeomClassID : int
101 {
102 SphereClass,
103 BoxClass,
104 CapsuleClass,
105 CylinderClass,
106 PlaneClass,
107 RayClass,
108 ConvexClass,
109 GeomTransformClass,
110 TriMeshClass,
111 HeightfieldClass,
112 FirstSpaceClass,
113 SimpleSpaceClass = FirstSpaceClass,
114 HashSpaceClass,
115 QuadTreeSpaceClass,
116 LastSpaceClass = QuadTreeSpaceClass,
117 ubtTerrainClass,
118 FirstUserClass,
119 LastUserClass = FirstUserClass + MaxUserClasses - 1,
120 NumClasses,
121 MaxUserClasses = 5
122 }
123
124 public enum JointType : int
125 {
126 None,
127 Ball,
128 Hinge,
129 Slider,
130 Contact,
131 Universal,
132 Hinge2,
133 Fixed,
134 Null,
135 AMotor,
136 LMotor,
137 Plane2D
138 }
139
140 public enum JointParam : int
141 {
142 LoStop,
143 HiStop,
144 Vel,
145 FMax,
146 FudgeFactor,
147 Bounce,
148 CFM,
149 StopERP,
150 StopCFM,
151 SuspensionERP,
152 SuspensionCFM,
153 LoStop2 = 256,
154 HiStop2,
155 Vel2,
156 FMax2,
157 FudgeFactor2,
158 Bounce2,
159 CFM2,
160 StopERP2,
161 StopCFM2,
162 SuspensionERP2,
163 SuspensionCFM2,
164 LoStop3 = 512,
165 HiStop3,
166 Vel3,
167 FMax3,
168 FudgeFactor3,
169 Bounce3,
170 CFM3,
171 StopERP3,
172 StopCFM3,
173 SuspensionERP3,
174 SuspensionCFM3
175 }
176
177 public enum dSweepAndPruneAxis : int
178 {
179 XYZ = ((0)|(1<<2)|(2<<4)),
180 XZY = ((0)|(2<<2)|(1<<4)),
181 YXZ = ((1)|(0<<2)|(2<<4)),
182 YZX = ((1)|(2<<2)|(0<<4)),
183 ZXY = ((2)|(0<<2)|(1<<4)),
184 ZYX = ((2)|(1<<2)|(0<<4))
185 }
186
187 #endregion
188
189 #region Callbacks
190
191 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
192 public delegate int AABBTestFn(IntPtr o1, IntPtr o2, ref AABB aabb);
193
194 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
195 public delegate int ColliderFn(IntPtr o1, IntPtr o2, int flags, out ContactGeom contact, int skip);
196
197 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
198 public delegate void GetAABBFn(IntPtr geom, out AABB aabb);
199
200 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
201 public delegate ColliderFn GetColliderFnFn(int num);
202
203 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
204 public delegate void GeomDtorFn(IntPtr o);
205
206 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
207 public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z);
208
209 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
210 public delegate dReal OSTerrainGetHeight(IntPtr p_user_data, int x, int z);
211
212 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
213 public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2);
214
215 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
216 public delegate int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex);
217
218 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
219 public delegate int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount);
220
221 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
222 public delegate int TriRayCallback(IntPtr trimesh, IntPtr ray, int triangleIndex, dReal u, dReal v);
223
224 #endregion
225
226 #region Structs
227
228 [StructLayout(LayoutKind.Sequential)]
229 public struct AABB
230 {
231 public dReal MinX, MaxX;
232 public dReal MinY, MaxY;
233 public dReal MinZ, MaxZ;
234 }
235
236
237 [StructLayout(LayoutKind.Sequential)]
238 public struct Contact
239 {
240 public SurfaceParameters surface;
241 public ContactGeom geom;
242 public Vector3 fdir1;
243 public static readonly int unmanagedSizeOf = Marshal.SizeOf(typeof(Contact));
244 }
245
246
247 [StructLayout(LayoutKind.Sequential)]
248 public struct ContactGeom
249 {
250
251 public Vector3 pos;
252 public Vector3 normal;
253 public dReal depth;
254 public IntPtr g1;
255 public IntPtr g2;
256 public int side1;
257 public int side2;
258 public static readonly int unmanagedSizeOf = Marshal.SizeOf(typeof(ContactGeom));
259 }
260
261 [StructLayout(LayoutKind.Sequential)]
262 public struct GeomClass
263 {
264 public int bytes;
265 public GetColliderFnFn collider;
266 public GetAABBFn aabb;
267 public AABBTestFn aabb_test;
268 public GeomDtorFn dtor;
269 }
270
271
272 [StructLayout(LayoutKind.Sequential)]
273 public struct JointFeedback
274 {
275 public Vector3 f1;
276 public Vector3 t1;
277 public Vector3 f2;
278 public Vector3 t2;
279 }
280
281
282 [StructLayout(LayoutKind.Sequential)]
283 public struct Mass
284 {
285 public dReal mass;
286 public Vector4 c;
287 public Matrix3 I;
288 }
289
290
291 [StructLayout(LayoutKind.Sequential)]
292 public struct Matrix3
293 {
294 public Matrix3(dReal m00, dReal m10, dReal m20, dReal m01, dReal m11, dReal m21, dReal m02, dReal m12, dReal m22)
295 {
296 M00 = m00; M10 = m10; M20 = m20; _m30 = 0.0f;
297 M01 = m01; M11 = m11; M21 = m21; _m31 = 0.0f;
298 M02 = m02; M12 = m12; M22 = m22; _m32 = 0.0f;
299 }
300 public dReal M00, M10, M20;
301 private dReal _m30;
302 public dReal M01, M11, M21;
303 private dReal _m31;
304 public dReal M02, M12, M22;
305 private dReal _m32;
306 }
307
308 [StructLayout(LayoutKind.Sequential)]
309 public struct Matrix4
310 {
311 public Matrix4(dReal m00, dReal m10, dReal m20, dReal m30,
312 dReal m01, dReal m11, dReal m21, dReal m31,
313 dReal m02, dReal m12, dReal m22, dReal m32,
314 dReal m03, dReal m13, dReal m23, dReal m33)
315 {
316 M00 = m00; M10 = m10; M20 = m20; M30 = m30;
317 M01 = m01; M11 = m11; M21 = m21; M31 = m31;
318 M02 = m02; M12 = m12; M22 = m22; M32 = m32;
319 M03 = m03; M13 = m13; M23 = m23; M33 = m33;
320 }
321 public dReal M00, M10, M20, M30;
322 public dReal M01, M11, M21, M31;
323 public dReal M02, M12, M22, M32;
324 public dReal M03, M13, M23, M33;
325 }
326
327 [StructLayout(LayoutKind.Sequential)]
328 public struct Quaternion
329 {
330 public dReal W, X, Y, Z;
331 }
332
333
334 [StructLayout(LayoutKind.Sequential)]
335 public struct SurfaceParameters
336 {
337 public ContactFlags mode;
338 public dReal mu;
339 public dReal mu2;
340 public dReal bounce;
341 public dReal bounce_vel;
342 public dReal soft_erp;
343 public dReal soft_cfm;
344 public dReal motion1;
345 public dReal motion2;
346 public dReal motionN;
347 public dReal slip1;
348 public dReal slip2;
349 }
350
351
352 [StructLayout(LayoutKind.Sequential)]
353 public struct Vector3
354 {
355 public Vector3(dReal x, dReal y, dReal z)
356 {
357 X = x; Y = y; Z = z; _w = 0.0f;
358 }
359 public dReal X, Y, Z;
360 private dReal _w;
361 }
362
363
364 [StructLayout(LayoutKind.Sequential)]
365 public struct Vector4
366 {
367 public Vector4(dReal x, dReal y, dReal z, dReal w)
368 {
369 X = x; Y = y; Z = z; W = w;
370 }
371 public dReal X, Y, Z, W;
372 }
373
374 #endregion
375
376 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAllocateODEDataForThread"), SuppressUnmanagedCodeSecurity]
377 public static extern int AllocateODEDataForThread(uint ODEInitFlags);
378
379 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAreConnected"), SuppressUnmanagedCodeSecurity]
380 public static extern bool AreConnected(IntPtr b1, IntPtr b2);
381
382 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dAreConnectedExcluding"), SuppressUnmanagedCodeSecurity]
383 public static extern bool AreConnectedExcluding(IntPtr b1, IntPtr b2, JointType joint_type);
384
385 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForce"), SuppressUnmanagedCodeSecurity]
386 public static extern void BodyAddForce(IntPtr body, dReal fx, dReal fy, dReal fz);
387
388 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForceAtPos"), SuppressUnmanagedCodeSecurity]
389 public static extern void BodyAddForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
390
391 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddForceAtRelPos"), SuppressUnmanagedCodeSecurity]
392 public static extern void BodyAddForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
393
394 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForce"), SuppressUnmanagedCodeSecurity]
395 public static extern void BodyAddRelForce(IntPtr body, dReal fx, dReal fy, dReal fz);
396
397 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForceAtPos"), SuppressUnmanagedCodeSecurity]
398 public static extern void BodyAddRelForceAtPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
399
400 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelForceAtRelPos"), SuppressUnmanagedCodeSecurity]
401 public static extern void BodyAddRelForceAtRelPos(IntPtr body, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz);
402
403 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddRelTorque"), SuppressUnmanagedCodeSecurity]
404 public static extern void BodyAddRelTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
405
406 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyAddTorque"), SuppressUnmanagedCodeSecurity]
407 public static extern void BodyAddTorque(IntPtr body, dReal fx, dReal fy, dReal fz);
408
409 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
410 public static extern void BodyCopyPosition(IntPtr body, out Vector3 pos);
411
412 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyPosition"), SuppressUnmanagedCodeSecurity]
413 public static extern void BodyCopyPosition(IntPtr body, out dReal X);
414
415 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
416 public static extern void BodyCopyQuaternion(IntPtr body, out Quaternion quat);
417
418 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyQuaternion"), SuppressUnmanagedCodeSecurity]
419 public static extern void BodyCopyQuaternion(IntPtr body, out dReal X);
420
421 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
422 public static extern void BodyCopyRotation(IntPtr body, out Matrix3 R);
423
424 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCopyRotation"), SuppressUnmanagedCodeSecurity]
425 public static extern void BodyCopyRotation(IntPtr body, out dReal M00);
426
427 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyCreate"), SuppressUnmanagedCodeSecurity]
428 public static extern IntPtr BodyiCreate(IntPtr world);
429 public static IntPtr BodyCreate(IntPtr world)
430 {
431 NTotalBodies++;
432 return BodyiCreate(world);
433 }
434
435 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyDestroy"), SuppressUnmanagedCodeSecurity]
436 public static extern void BodyiDestroy(IntPtr body);
437 public static void BodyDestroy(IntPtr body)
438 {
439 NTotalBodies--;
440 BodyiDestroy(body);
441 }
442
443 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyDisable"), SuppressUnmanagedCodeSecurity]
444 public static extern void BodyDisable(IntPtr body);
445
446 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyEnable"), SuppressUnmanagedCodeSecurity]
447 public static extern void BodyEnable(IntPtr body);
448
449 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
450 public static extern dReal BodyGetAutoDisableAngularThreshold(IntPtr body);
451
452 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
453 public static extern bool BodyGetAutoDisableFlag(IntPtr body);
454
455 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
456 public static extern void BodyGetAutoDisableDefaults(IntPtr body);
457
458 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
459 public static extern dReal BodyGetAutoDisableLinearThreshold(IntPtr body);
460
461 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
462 public static extern int BodyGetAutoDisableSteps(IntPtr body);
463
464 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
465 public static extern dReal BodyGetAutoDisableTime(IntPtr body);
466
467 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularVel"), SuppressUnmanagedCodeSecurity]
468 public extern unsafe static Vector3* BodyGetAngularVelUnsafe(IntPtr body);
469 public static Vector3 BodyGetAngularVel(IntPtr body)
470 {
471 unsafe { return *(BodyGetAngularVelUnsafe(body)); }
472 }
473
474 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetData"), SuppressUnmanagedCodeSecurity]
475 public static extern IntPtr BodyGetData(IntPtr body);
476
477 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
478 public static extern int BodyGetFiniteRotationMode(IntPtr body);
479
480 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
481 public static extern void BodyGetFiniteRotationAxis(IntPtr body, out Vector3 result);
482
483 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetForce"), SuppressUnmanagedCodeSecurity]
484 public extern unsafe static Vector3* BodyGetForceUnsafe(IntPtr body);
485 public static Vector3 BodyGetForce(IntPtr body)
486 {
487 unsafe { return *(BodyGetForceUnsafe(body)); }
488 }
489
490 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetGravityMode"), SuppressUnmanagedCodeSecurity]
491 public static extern bool BodyGetGravityMode(IntPtr body);
492
493 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetGyroscopicMode"), SuppressUnmanagedCodeSecurity]
494 public static extern int BodyGetGyroscopicMode(IntPtr body);
495
496 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetJoint"), SuppressUnmanagedCodeSecurity]
497 public static extern IntPtr BodyGetJoint(IntPtr body, int index);
498
499 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearVel"), SuppressUnmanagedCodeSecurity]
500 public extern unsafe static Vector3* BodyGetLinearVelUnsafe(IntPtr body);
501 public static Vector3 BodyGetLinearVel(IntPtr body)
502 {
503 unsafe { return *(BodyGetLinearVelUnsafe(body)); }
504 }
505
506 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetMass"), SuppressUnmanagedCodeSecurity]
507 public static extern void BodyGetMass(IntPtr body, out Mass mass);
508
509 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetNumJoints"), SuppressUnmanagedCodeSecurity]
510 public static extern int BodyGetNumJoints(IntPtr body);
511
512 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPointVel"), SuppressUnmanagedCodeSecurity]
513 public static extern void BodyGetPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
514
515 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPosition"), SuppressUnmanagedCodeSecurity]
516 public extern unsafe static Vector3* BodyGetPositionUnsafe(IntPtr body);
517 public static Vector3 BodyGetPosition(IntPtr body)
518 {
519 unsafe { return *(BodyGetPositionUnsafe(body)); }
520 }
521
522 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetPosRelPoint"), SuppressUnmanagedCodeSecurity]
523 public static extern void BodyGetPosRelPoint(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
524
525 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetQuaternion"), SuppressUnmanagedCodeSecurity]
526 public extern unsafe static Quaternion* BodyGetQuaternionUnsafe(IntPtr body);
527 public static Quaternion BodyGetQuaternion(IntPtr body)
528 {
529 unsafe { return *(BodyGetQuaternionUnsafe(body)); }
530 }
531
532 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRelPointPos"), SuppressUnmanagedCodeSecurity]
533 public static extern void BodyGetRelPointPos(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
534
535 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRelPointVel"), SuppressUnmanagedCodeSecurity]
536 public static extern void BodyGetRelPointVel(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
537
538 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetRotation"), SuppressUnmanagedCodeSecurity]
539 public extern unsafe static Matrix3* BodyGetRotationUnsafe(IntPtr body);
540 public static Matrix3 BodyGetRotation(IntPtr body)
541 {
542 unsafe { return *(BodyGetRotationUnsafe(body)); }
543 }
544
545 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetTorque"), SuppressUnmanagedCodeSecurity]
546 public extern unsafe static Vector3* BodyGetTorqueUnsafe(IntPtr body);
547 public static Vector3 BodyGetTorque(IntPtr body)
548 {
549 unsafe { return *(BodyGetTorqueUnsafe(body)); }
550 }
551
552 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetWorld"), SuppressUnmanagedCodeSecurity]
553 public static extern IntPtr BodyGetWorld(IntPtr body);
554
555 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetFirstGeom"), SuppressUnmanagedCodeSecurity]
556 public static extern IntPtr BodyGetFirstGeom(IntPtr body);
557
558 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetNextGeom"), SuppressUnmanagedCodeSecurity]
559 public static extern IntPtr dBodyGetNextGeom(IntPtr Geom);
560
561
562 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyIsEnabled"), SuppressUnmanagedCodeSecurity]
563 public static extern bool BodyIsEnabled(IntPtr body);
564
565 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularVel"), SuppressUnmanagedCodeSecurity]
566 public static extern void BodySetAngularVel(IntPtr body, dReal x, dReal y, dReal z);
567
568 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
569 public static extern void BodySetAutoDisableAngularThreshold(IntPtr body, dReal angular_threshold);
570
571 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableDefaults"), SuppressUnmanagedCodeSecurity]
572 public static extern void BodySetAutoDisableDefaults(IntPtr body);
573
574 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
575 public static extern void BodySetAutoDisableFlag(IntPtr body, bool do_auto_disable);
576
577 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
578 public static extern void BodySetAutoDisableLinearThreshold(IntPtr body, dReal linear_threshold);
579
580 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
581 public static extern void BodySetAutoDisableSteps(IntPtr body, int steps);
582
583 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
584 public static extern void BodySetAutoDisableTime(IntPtr body, dReal time);
585
586 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetData"), SuppressUnmanagedCodeSecurity]
587 public static extern void BodySetData(IntPtr body, IntPtr data);
588
589 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetFiniteRotationMode"), SuppressUnmanagedCodeSecurity]
590 public static extern void BodySetFiniteRotationMode(IntPtr body, int mode);
591
592 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetFiniteRotationAxis"), SuppressUnmanagedCodeSecurity]
593 public static extern void BodySetFiniteRotationAxis(IntPtr body, dReal x, dReal y, dReal z);
594
595 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearDamping"), SuppressUnmanagedCodeSecurity]
596 public static extern void BodySetLinearDamping(IntPtr body, dReal scale);
597
598 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDamping"), SuppressUnmanagedCodeSecurity]
599 public static extern void BodySetAngularDamping(IntPtr body, dReal scale);
600
601 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearDamping"), SuppressUnmanagedCodeSecurity]
602 public static extern dReal BodyGetLinearDamping(IntPtr body);
603
604 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularDamping"), SuppressUnmanagedCodeSecurity]
605 public static extern dReal BodyGetAngularDamping(IntPtr body);
606
607 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDamping"), SuppressUnmanagedCodeSecurity]
608 public static extern void BodySetDamping(IntPtr body, dReal linear_scale, dReal angular_scale);
609
610 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
611 public static extern void BodySetAngularDampingThreshold(IntPtr body, dReal threshold);
612
613 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
614 public static extern void BodySetLinearDampingThreshold(IntPtr body, dReal threshold);
615
616 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
617 public static extern dReal BodyGetLinearDampingThreshold(IntPtr body);
618
619 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyGetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
620 public static extern dReal BodyGetAngularDampingThreshold(IntPtr body);
621
622 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetForce"), SuppressUnmanagedCodeSecurity]
623 public static extern void BodySetForce(IntPtr body, dReal x, dReal y, dReal z);
624
625 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetGravityMode"), SuppressUnmanagedCodeSecurity]
626 public static extern void BodySetGravityMode(IntPtr body, bool mode);
627
628 /// <summary>
629 /// Sets the Gyroscopic term status on the body specified.
630 /// </summary>
631 /// <param name="body">Pointer to body</param>
632 /// <param name="enabled">NonZero enabled, Zero disabled</param>
633 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetGyroscopicMode"), SuppressUnmanagedCodeSecurity]
634 public static extern void dBodySetGyroscopicMode(IntPtr body, int enabled);
635
636 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetLinearVel"), SuppressUnmanagedCodeSecurity]
637 public static extern void BodySetLinearVel(IntPtr body, dReal x, dReal y, dReal z);
638
639 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetMass"), SuppressUnmanagedCodeSecurity]
640 public static extern void BodySetMass(IntPtr body, ref Mass mass);
641
642 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetPosition"), SuppressUnmanagedCodeSecurity]
643 public static extern void BodySetPosition(IntPtr body, dReal x, dReal y, dReal z);
644
645 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
646 public static extern void BodySetQuaternion(IntPtr body, ref Quaternion q);
647
648 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetQuaternion"), SuppressUnmanagedCodeSecurity]
649 public static extern void BodySetQuaternion(IntPtr body, ref dReal w);
650
651 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
652 public static extern void BodySetRotation(IntPtr body, ref Matrix3 R);
653
654 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetRotation"), SuppressUnmanagedCodeSecurity]
655 public static extern void BodySetRotation(IntPtr body, ref dReal M00);
656
657 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodySetTorque"), SuppressUnmanagedCodeSecurity]
658 public static extern void BodySetTorque(IntPtr body, dReal x, dReal y, dReal z);
659
660 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyVectorFromWorld"), SuppressUnmanagedCodeSecurity]
661 public static extern void BodyVectorFromWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
662
663 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBodyVectorToWorld"), SuppressUnmanagedCodeSecurity]
664 public static extern void BodyVectorToWorld(IntPtr body, dReal px, dReal py, dReal pz, out Vector3 result);
665
666 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBoxBox"), SuppressUnmanagedCodeSecurity]
667 public static extern void BoxBox(ref Vector3 p1, ref Matrix3 R1,
668 ref Vector3 side1, ref Vector3 p2,
669 ref Matrix3 R2, ref Vector3 side2,
670 ref Vector3 normal, out dReal depth, out int return_code,
671 int maxc, out ContactGeom contact, int skip);
672
673 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dBoxTouchesBox"), SuppressUnmanagedCodeSecurity]
674 public static extern void BoxTouchesBox(ref Vector3 _p1, ref Matrix3 R1,
675 ref Vector3 side1, ref Vector3 _p2,
676 ref Matrix3 R2, ref Vector3 side2);
677
678 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCleanupODEAllDataForThread"), SuppressUnmanagedCodeSecurity]
679 public static extern void CleanupODEAllDataForThread();
680
681 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dClosestLineSegmentPoints"), SuppressUnmanagedCodeSecurity]
682 public static extern void ClosestLineSegmentPoints(ref Vector3 a1, ref Vector3 a2,
683 ref Vector3 b1, ref Vector3 b2,
684 ref Vector3 cp1, ref Vector3 cp2);
685
686 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCloseODE"), SuppressUnmanagedCodeSecurity]
687 public static extern void CloseODE();
688
689 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
690 public static extern int Collide(IntPtr o1, IntPtr o2, int flags, [In, Out] ContactGeom[] contact, int skip);
691 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCollide"), SuppressUnmanagedCodeSecurity]
692 public static extern int CollidePtr(IntPtr o1, IntPtr o2, int flags, IntPtr contactgeomarray, int skip);
693
694 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dConnectingJoint"), SuppressUnmanagedCodeSecurity]
695 public static extern IntPtr ConnectingJoint(IntPtr j1, IntPtr j2);
696
697 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateBox"), SuppressUnmanagedCodeSecurity]
698 public static extern IntPtr CreateiBox(IntPtr space, dReal lx, dReal ly, dReal lz);
699 public static IntPtr CreateBox(IntPtr space, dReal lx, dReal ly, dReal lz)
700 {
701 NTotalGeoms++;
702 return CreateiBox(space, lx, ly, lz);
703 }
704
705 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateCapsule"), SuppressUnmanagedCodeSecurity]
706 public static extern IntPtr CreateiCapsule(IntPtr space, dReal radius, dReal length);
707 public static IntPtr CreateCapsule(IntPtr space, dReal radius, dReal length)
708 {
709 NTotalGeoms++;
710 return CreateiCapsule(space, radius, length);
711 }
712
713 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateConvex"), SuppressUnmanagedCodeSecurity]
714 public static extern IntPtr CreateiConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
715 public static IntPtr CreateConvex(IntPtr space, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons)
716 {
717 NTotalGeoms++;
718 return CreateiConvex(space, planes, planeCount, points, pointCount, polygons);
719 }
720
721 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateCylinder"), SuppressUnmanagedCodeSecurity]
722 public static extern IntPtr CreateiCylinder(IntPtr space, dReal radius, dReal length);
723 public static IntPtr CreateCylinder(IntPtr space, dReal radius, dReal length)
724 {
725 NTotalGeoms++;
726 return CreateiCylinder(space, radius, length);
727 }
728
729 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateHeightfield"), SuppressUnmanagedCodeSecurity]
730 public static extern IntPtr CreateiHeightfield(IntPtr space, IntPtr data, int bPlaceable);
731 public static IntPtr CreateHeightfield(IntPtr space, IntPtr data, int bPlaceable)
732 {
733 NTotalGeoms++;
734 return CreateiHeightfield(space, data, bPlaceable);
735 }
736
737 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateOSTerrain"), SuppressUnmanagedCodeSecurity]
738 public static extern IntPtr CreateiOSTerrain(IntPtr space, IntPtr data, int bPlaceable);
739 public static IntPtr CreateOSTerrain(IntPtr space, IntPtr data, int bPlaceable)
740 {
741 NTotalGeoms++;
742 return CreateiOSTerrain(space, data, bPlaceable);
743 }
744
745
746
747
748
749 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity]
750 public static extern IntPtr CreateiGeom(int classnum);
751 public static IntPtr CreateGeom(int classnum)
752 {
753 NTotalGeoms++;
754 return CreateiGeom(classnum);
755 }
756
757 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeomClass"), SuppressUnmanagedCodeSecurity]
758 public static extern int CreateGeomClass(ref GeomClass classptr);
759
760 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeomTransform"), SuppressUnmanagedCodeSecurity]
761 public static extern IntPtr CreateGeomTransform(IntPtr space);
762
763 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreatePlane"), SuppressUnmanagedCodeSecurity]
764 public static extern IntPtr CreateiPlane(IntPtr space, dReal a, dReal b, dReal c, dReal d);
765 public static IntPtr CreatePlane(IntPtr space, dReal a, dReal b, dReal c, dReal d)
766 {
767 NTotalGeoms++;
768 return CreateiPlane(space, a, b, c, d);
769 }
770
771 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateRay"), SuppressUnmanagedCodeSecurity]
772 public static extern IntPtr CreateiRay(IntPtr space, dReal length);
773 public static IntPtr CreateRay(IntPtr space, dReal length)
774 {
775 NTotalGeoms++;
776 return CreateiRay(space, length);
777 }
778
779 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateSphere"), SuppressUnmanagedCodeSecurity]
780 public static extern IntPtr CreateiSphere(IntPtr space, dReal radius);
781 public static IntPtr CreateSphere(IntPtr space, dReal radius)
782 {
783 NTotalGeoms++;
784 return CreateiSphere(space, radius);
785 }
786
787 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateTriMesh"), SuppressUnmanagedCodeSecurity]
788 public static extern IntPtr CreateiTriMesh(IntPtr space, IntPtr data,
789 TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback);
790 public static IntPtr CreateTriMesh(IntPtr space, IntPtr data,
791 TriCallback callback, TriArrayCallback arrayCallback, TriRayCallback rayCallback)
792 {
793 NTotalGeoms++;
794 return CreateiTriMesh(space, data, callback, arrayCallback, rayCallback);
795 }
796 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dDot"), SuppressUnmanagedCodeSecurity]
797 public static extern dReal Dot(ref dReal X0, ref dReal X1, int n);
798
799 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dDQfromW"), SuppressUnmanagedCodeSecurity]
800 public static extern void DQfromW(dReal[] dq, ref Vector3 w, ref Quaternion q);
801
802 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dFactorCholesky"), SuppressUnmanagedCodeSecurity]
803 public static extern int FactorCholesky(ref dReal A00, int n);
804
805 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dFactorLDLT"), SuppressUnmanagedCodeSecurity]
806 public static extern void FactorLDLT(ref dReal A, out dReal d, int n, int nskip);
807
808 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
809 public static extern void GeomBoxGetLengths(IntPtr geom, out Vector3 len);
810
811 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxGetLengths"), SuppressUnmanagedCodeSecurity]
812 public static extern void GeomBoxGetLengths(IntPtr geom, out dReal x);
813
814 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxPointDepth"), SuppressUnmanagedCodeSecurity]
815 public static extern dReal GeomBoxPointDepth(IntPtr geom, dReal x, dReal y, dReal z);
816
817 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomBoxSetLengths"), SuppressUnmanagedCodeSecurity]
818 public static extern void GeomBoxSetLengths(IntPtr geom, dReal x, dReal y, dReal z);
819
820 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsuleGetParams"), SuppressUnmanagedCodeSecurity]
821 public static extern void GeomCapsuleGetParams(IntPtr geom, out dReal radius, out dReal length);
822
823 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsulePointDepth"), SuppressUnmanagedCodeSecurity]
824 public static extern dReal GeomCapsulePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
825
826 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCapsuleSetParams"), SuppressUnmanagedCodeSecurity]
827 public static extern void GeomCapsuleSetParams(IntPtr geom, dReal radius, dReal length);
828
829 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomClearOffset"), SuppressUnmanagedCodeSecurity]
830 public static extern void GeomClearOffset(IntPtr geom);
831
832 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
833 public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref Vector3 pos);
834
835 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetPosition"), SuppressUnmanagedCodeSecurity]
836 public static extern IntPtr GeomCopyOffsetPosition(IntPtr geom, ref dReal X);
837
838 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
839 public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref Quaternion Q);
840
841 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
842 public static extern void GeomCopyOffsetQuaternion(IntPtr geom, ref dReal X);
843
844 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
845 public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref Matrix3 R);
846
847 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyOffsetRotation"), SuppressUnmanagedCodeSecurity]
848 public static extern IntPtr GeomCopyOffsetRotation(IntPtr geom, ref dReal M00);
849
850 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
851 public static extern void GeomCopyPosition(IntPtr geom, out Vector3 pos);
852
853 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyPosition"), SuppressUnmanagedCodeSecurity]
854 public static extern void GeomCopyPosition(IntPtr geom, out dReal X);
855
856 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
857 public static extern void GeomCopyRotation(IntPtr geom, out Matrix3 R);
858
859 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCopyRotation"), SuppressUnmanagedCodeSecurity]
860 public static extern void GeomCopyRotation(IntPtr geom, out dReal M00);
861
862 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCylinderGetParams"), SuppressUnmanagedCodeSecurity]
863 public static extern void GeomCylinderGetParams(IntPtr geom, out dReal radius, out dReal length);
864
865 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomCylinderSetParams"), SuppressUnmanagedCodeSecurity]
866 public static extern void GeomCylinderSetParams(IntPtr geom, dReal radius, dReal length);
867
868 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomDestroy"), SuppressUnmanagedCodeSecurity]
869 public static extern void GeomiDestroy(IntPtr geom);
870 public static void GeomDestroy(IntPtr geom)
871 {
872 NTotalGeoms--;
873 GeomiDestroy(geom);
874 }
875
876
877 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomDisable"), SuppressUnmanagedCodeSecurity]
878 public static extern void GeomDisable(IntPtr geom);
879
880 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomEnable"), SuppressUnmanagedCodeSecurity]
881 public static extern void GeomEnable(IntPtr geom);
882
883 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
884 public static extern void GeomGetAABB(IntPtr geom, out AABB aabb);
885
886 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetAABB"), SuppressUnmanagedCodeSecurity]
887 public static extern void GeomGetAABB(IntPtr geom, out dReal minX);
888
889 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetBody"), SuppressUnmanagedCodeSecurity]
890 public static extern IntPtr GeomGetBody(IntPtr geom);
891
892 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCategoryBits"), SuppressUnmanagedCodeSecurity]
893 public static extern uint GeomGetCategoryBits(IntPtr geom);
894
895 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClassData"), SuppressUnmanagedCodeSecurity]
896 public static extern IntPtr GeomGetClassData(IntPtr geom);
897
898 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetCollideBits"), SuppressUnmanagedCodeSecurity]
899 public static extern uint GeomGetCollideBits(IntPtr geom);
900
901 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetClass"), SuppressUnmanagedCodeSecurity]
902 public static extern GeomClassID GeomGetClass(IntPtr geom);
903
904 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetData"), SuppressUnmanagedCodeSecurity]
905 public static extern IntPtr GeomGetData(IntPtr geom);
906
907 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetPosition"), SuppressUnmanagedCodeSecurity]
908 public extern unsafe static Vector3* GeomGetOffsetPositionUnsafe(IntPtr geom);
909 public static Vector3 GeomGetOffsetPosition(IntPtr geom)
910 {
911 unsafe { return *(GeomGetOffsetPositionUnsafe(geom)); }
912 }
913
914 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetOffsetRotation"), SuppressUnmanagedCodeSecurity]
915 public extern unsafe static Matrix3* GeomGetOffsetRotationUnsafe(IntPtr geom);
916 public static Matrix3 GeomGetOffsetRotation(IntPtr geom)
917 {
918 unsafe { return *(GeomGetOffsetRotationUnsafe(geom)); }
919 }
920
921 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetPosition"), SuppressUnmanagedCodeSecurity]
922 public extern unsafe static Vector3* GeomGetPositionUnsafe(IntPtr geom);
923 public static Vector3 GeomGetPosition(IntPtr geom)
924 {
925 unsafe { return *(GeomGetPositionUnsafe(geom)); }
926 }
927 public static OMV.Vector3 GeomGetPositionOMV(IntPtr geom)
928 {
929 Vector3 vtmp = GeomGetPosition(geom);
930 return new OMV.Vector3(vtmp.X, vtmp.Y, vtmp.Z);
931 }
932
933 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
934 public static extern void GeomCopyQuaternion(IntPtr geom, out Quaternion q);
935 public static OMV.Quaternion GeomGetQuaternionOMV(IntPtr geom)
936 {
937 Quaternion qtmp;
938 GeomCopyQuaternion(geom, out qtmp);
939 return new OMV.Quaternion(qtmp.X, qtmp.Y, qtmp.Z, qtmp.W);
940 }
941
942 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetQuaternion"), SuppressUnmanagedCodeSecurity]
943 public static extern void GeomCopyQuaternion(IntPtr geom, out dReal X);
944
945 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetRotation"), SuppressUnmanagedCodeSecurity]
946 public extern unsafe static Matrix3* GeomGetRotationUnsafe(IntPtr geom);
947 public static Matrix3 GeomGetRotation(IntPtr geom)
948 {
949 unsafe { return *(GeomGetRotationUnsafe(geom)); }
950 }
951
952 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomGetSpace"), SuppressUnmanagedCodeSecurity]
953 public static extern IntPtr GeomGetSpace(IntPtr geom);
954
955 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
956 public static extern void GeomHeightfieldDataBuildByte(IntPtr d, byte[] pHeightData, int bCopyHeightData,
957 dReal width, dReal depth, int widthSamples, int depthSamples,
958 dReal scale, dReal offset, dReal thickness, int bWrap);
959
960 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildByte"), SuppressUnmanagedCodeSecurity]
961 public static extern void GeomHeightfieldDataBuildByte(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
962 dReal width, dReal depth, int widthSamples, int depthSamples,
963 dReal scale, dReal offset, dReal thickness, int bWrap);
964
965 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildCallback"), SuppressUnmanagedCodeSecurity]
966 public static extern void GeomHeightfieldDataBuildCallback(IntPtr d, IntPtr pUserData, HeightfieldGetHeight pCallback,
967 dReal width, dReal depth, int widthSamples, int depthSamples,
968 dReal scale, dReal offset, dReal thickness, int bWrap);
969
970 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
971 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, ushort[] pHeightData, int bCopyHeightData,
972 dReal width, dReal depth, int widthSamples, int depthSamples,
973 dReal scale, dReal offset, dReal thickness, int bWrap);
974
975 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
976 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, short[] pHeightData, int bCopyHeightData,
977 dReal width, dReal depth, int widthSamples, int depthSamples,
978 dReal scale, dReal offset, dReal thickness, int bWrap);
979
980 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildShort"), SuppressUnmanagedCodeSecurity]
981 public static extern void GeomHeightfieldDataBuildShort(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
982 dReal width, dReal depth, int widthSamples, int depthSamples,
983 dReal scale, dReal offset, dReal thickness, int bWrap);
984
985 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
986 public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, float[] pHeightData, int bCopyHeightData,
987 dReal width, dReal depth, int widthSamples, int depthSamples,
988 dReal scale, dReal offset, dReal thickness, int bWrap);
989
990 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildSingle"), SuppressUnmanagedCodeSecurity]
991 public static extern void GeomHeightfieldDataBuildSingle(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
992 dReal width, dReal depth, int widthSamples, int depthSamples,
993 dReal scale, dReal offset, dReal thickness, int bWrap);
994
995
996
997 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
998 public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData,
999 dReal width, dReal depth, int widthSamples, int depthSamples,
1000 dReal scale, dReal offset, dReal thickness, int bWrap);
1001
1002 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1003 public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
1004 dReal width, dReal depth, int widthSamples, int depthSamples,
1005 dReal scale, dReal offset, dReal thickness, int bWrap);
1006
1007 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataCreate"), SuppressUnmanagedCodeSecurity]
1008 public static extern IntPtr GeomHeightfieldDataCreate();
1009
1010 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataDestroy"), SuppressUnmanagedCodeSecurity]
1011 public static extern void GeomHeightfieldDataDestroy(IntPtr d);
1012
1013 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataSetBounds"), SuppressUnmanagedCodeSecurity]
1014 public static extern void GeomHeightfieldDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
1015
1016 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1017 public static extern IntPtr GeomHeightfieldGetHeightfieldData(IntPtr g);
1018
1019 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1020 public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d);
1021
1022
1023 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
1024 public static extern void GeomOSTerrainDataBuild(IntPtr d, float[] pHeightData, int bCopyHeightData,
1025 dReal sampleSize, int widthSamples, int depthSamples,
1026 dReal offset, dReal thickness, int bWrap);
1027
1028 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataBuild"), SuppressUnmanagedCodeSecurity]
1029 public static extern void GeomOSTerrainDataBuild(IntPtr d, IntPtr pHeightData, int bCopyHeightData,
1030 dReal sampleSize, int widthSamples, int depthSamples,
1031 dReal thickness, int bWrap);
1032
1033 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataCreate"), SuppressUnmanagedCodeSecurity]
1034 public static extern IntPtr GeomOSTerrainDataCreate();
1035
1036 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataDestroy"), SuppressUnmanagedCodeSecurity]
1037 public static extern void GeomOSTerrainDataDestroy(IntPtr d);
1038
1039 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainDataSetBounds"), SuppressUnmanagedCodeSecurity]
1040 public static extern void GeomOSTerrainDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight);
1041
1042 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainGetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1043 public static extern IntPtr GeomOSTerrainGetHeightfieldData(IntPtr g);
1044
1045 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomOSTerrainSetHeightfieldData"), SuppressUnmanagedCodeSecurity]
1046 public static extern void GeomOSTerrainSetHeightfieldData(IntPtr g, IntPtr d);
1047
1048
1049 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity]
1050 public static extern bool GeomIsEnabled(IntPtr geom);
1051
1052 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsOffset"), SuppressUnmanagedCodeSecurity]
1053 public static extern bool GeomIsOffset(IntPtr geom);
1054
1055 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsSpace"), SuppressUnmanagedCodeSecurity]
1056 public static extern bool GeomIsSpace(IntPtr geom);
1057
1058 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
1059 public static extern void GeomPlaneGetParams(IntPtr geom, ref Vector4 result);
1060
1061 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneGetParams"), SuppressUnmanagedCodeSecurity]
1062 public static extern void GeomPlaneGetParams(IntPtr geom, ref dReal A);
1063
1064 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlanePointDepth"), SuppressUnmanagedCodeSecurity]
1065 public static extern dReal GeomPlanePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
1066
1067 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomPlaneSetParams"), SuppressUnmanagedCodeSecurity]
1068 public static extern void GeomPlaneSetParams(IntPtr plane, dReal a, dReal b, dReal c, dReal d);
1069
1070 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
1071 public static extern void GeomRayGet(IntPtr ray, ref Vector3 start, ref Vector3 dir);
1072
1073 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGet"), SuppressUnmanagedCodeSecurity]
1074 public static extern void GeomRayGet(IntPtr ray, ref dReal startX, ref dReal dirX);
1075
1076 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetClosestHit"), SuppressUnmanagedCodeSecurity]
1077 public static extern int GeomRayGetClosestHit(IntPtr ray);
1078
1079 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetLength"), SuppressUnmanagedCodeSecurity]
1080 public static extern dReal GeomRayGetLength(IntPtr ray);
1081
1082 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRayGetParams"), SuppressUnmanagedCodeSecurity]
1083 public static extern dReal GeomRayGetParams(IntPtr g, out int firstContact, out int backfaceCull);
1084
1085 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySet"), SuppressUnmanagedCodeSecurity]
1086 public static extern void GeomRaySet(IntPtr ray, dReal px, dReal py, dReal pz, dReal dx, dReal dy, dReal dz);
1087
1088 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetClosestHit"), SuppressUnmanagedCodeSecurity]
1089 public static extern void GeomRaySetClosestHit(IntPtr ray, int closestHit);
1090
1091 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetLength"), SuppressUnmanagedCodeSecurity]
1092 public static extern void GeomRaySetLength(IntPtr ray, dReal length);
1093
1094 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomRaySetParams"), SuppressUnmanagedCodeSecurity]
1095 public static extern void GeomRaySetParams(IntPtr ray, int firstContact, int backfaceCull);
1096
1097 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetBody"), SuppressUnmanagedCodeSecurity]
1098 public static extern void GeomSetBody(IntPtr geom, IntPtr body);
1099
1100 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCategoryBits"), SuppressUnmanagedCodeSecurity]
1101 public static extern void GeomSetCategoryBits(IntPtr geom, uint bits);
1102
1103 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetCollideBits"), SuppressUnmanagedCodeSecurity]
1104 public static extern void GeomSetCollideBits(IntPtr geom, uint bits);
1105
1106 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetConvex"), SuppressUnmanagedCodeSecurity]
1107 public static extern IntPtr GeomSetConvex(IntPtr geom, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons);
1108
1109 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetData"), SuppressUnmanagedCodeSecurity]
1110 public static extern void GeomSetData(IntPtr geom, IntPtr data);
1111
1112 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetPosition"), SuppressUnmanagedCodeSecurity]
1113 public static extern void GeomSetOffsetPosition(IntPtr geom, dReal x, dReal y, dReal z);
1114
1115 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
1116 public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref Quaternion Q);
1117
1118 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetQuaternion"), SuppressUnmanagedCodeSecurity]
1119 public static extern void GeomSetOffsetQuaternion(IntPtr geom, ref dReal X);
1120
1121 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
1122 public static extern void GeomSetOffsetRotation(IntPtr geom, ref Matrix3 R);
1123
1124 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetRotation"), SuppressUnmanagedCodeSecurity]
1125 public static extern void GeomSetOffsetRotation(IntPtr geom, ref dReal M00);
1126
1127 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldPosition"), SuppressUnmanagedCodeSecurity]
1128 public static extern void GeomSetOffsetWorldPosition(IntPtr geom, dReal x, dReal y, dReal z);
1129
1130 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
1131 public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref Quaternion Q);
1132
1133 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldQuaternion"), SuppressUnmanagedCodeSecurity]
1134 public static extern void GeomSetOffsetWorldQuaternion(IntPtr geom, ref dReal X);
1135
1136 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
1137 public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref Matrix3 R);
1138
1139 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetOffsetWorldRotation"), SuppressUnmanagedCodeSecurity]
1140 public static extern void GeomSetOffsetWorldRotation(IntPtr geom, ref dReal M00);
1141
1142 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetPosition"), SuppressUnmanagedCodeSecurity]
1143 public static extern void GeomSetPosition(IntPtr geom, dReal x, dReal y, dReal z);
1144
1145 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
1146 public static extern void GeomSetQuaternion(IntPtr geom, ref Quaternion quat);
1147
1148 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetQuaternion"), SuppressUnmanagedCodeSecurity]
1149 public static extern void GeomSetQuaternion(IntPtr geom, ref dReal w);
1150
1151 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
1152 public static extern void GeomSetRotation(IntPtr geom, ref Matrix3 R);
1153
1154 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSetRotation"), SuppressUnmanagedCodeSecurity]
1155 public static extern void GeomSetRotation(IntPtr geom, ref dReal M00);
1156
1157 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSphereGetRadius"), SuppressUnmanagedCodeSecurity]
1158 public static extern dReal GeomSphereGetRadius(IntPtr geom);
1159
1160 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSpherePointDepth"), SuppressUnmanagedCodeSecurity]
1161 public static extern dReal GeomSpherePointDepth(IntPtr geom, dReal x, dReal y, dReal z);
1162
1163 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomSphereSetRadius"), SuppressUnmanagedCodeSecurity]
1164 public static extern void GeomSphereSetRadius(IntPtr geom, dReal radius);
1165
1166 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetCleanup"), SuppressUnmanagedCodeSecurity]
1167 public static extern int GeomTransformGetCleanup(IntPtr geom);
1168
1169 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetGeom"), SuppressUnmanagedCodeSecurity]
1170 public static extern IntPtr GeomTransformGetGeom(IntPtr geom);
1171
1172 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformGetInfo"), SuppressUnmanagedCodeSecurity]
1173 public static extern int GeomTransformGetInfo(IntPtr geom);
1174
1175 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetCleanup"), SuppressUnmanagedCodeSecurity]
1176 public static extern void GeomTransformSetCleanup(IntPtr geom, int mode);
1177
1178 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetGeom"), SuppressUnmanagedCodeSecurity]
1179 public static extern void GeomTransformSetGeom(IntPtr geom, IntPtr obj);
1180
1181 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTransformSetInfo"), SuppressUnmanagedCodeSecurity]
1182 public static extern void GeomTransformSetInfo(IntPtr geom, int info);
1183
1184 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1185 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1186 double[] vertices, int vertexStride, int vertexCount,
1187 int[] indices, int indexCount, int triStride);
1188
1189 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble"), SuppressUnmanagedCodeSecurity]
1190 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1191 IntPtr vertices, int vertexStride, int vertexCount,
1192 IntPtr indices, int indexCount, int triStride);
1193
1194 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
1195 public static extern void GeomTriMeshDataBuildDouble1(IntPtr d,
1196 double[] vertices, int vertexStride, int vertexCount,
1197 int[] indices, int indexCount, int triStride,
1198 double[] normals);
1199
1200 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildDouble1"), SuppressUnmanagedCodeSecurity]
1201 public static extern void GeomTriMeshDataBuildDouble(IntPtr d,
1202 IntPtr vertices, int vertexStride, int vertexCount,
1203 IntPtr indices, int indexCount, int triStride,
1204 IntPtr normals);
1205
1206 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
1207 public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
1208 dReal[] vertices, int vertexStride, int vertexCount,
1209 int[] indices, int indexCount, int triStride);
1210
1211 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple"), SuppressUnmanagedCodeSecurity]
1212 public static extern void GeomTriMeshDataBuildSingle(IntPtr d,
1213 IntPtr vertices, int vertexStride, int vertexCount,
1214 IntPtr indices, int indexCount, int triStride);
1215
1216 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
1217 public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
1218 dReal[] vertices, int vertexStride, int vertexCount,
1219 int[] indices, int indexCount, int triStride,
1220 dReal[] normals);
1221
1222 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSimple1"), SuppressUnmanagedCodeSecurity]
1223 public static extern void GeomTriMeshDataBuildSingle1(IntPtr d,
1224 IntPtr vertices, int vertexStride, int vertexCount,
1225 IntPtr indices, int indexCount, int triStride,
1226 IntPtr normals);
1227
1228 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
1229 public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
1230 float[] vertices, int vertexStride, int vertexCount,
1231 int[] indices, int indexCount, int triStride);
1232
1233 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle"), SuppressUnmanagedCodeSecurity]
1234 public static extern void GeomTriMeshDataBuildSimple(IntPtr d,
1235 IntPtr vertices, int vertexStride, int vertexCount,
1236 IntPtr indices, int indexCount, int triStride);
1237
1238 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
1239 public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
1240 float[] vertices, int vertexStride, int vertexCount,
1241 int[] indices, int indexCount, int triStride,
1242 float[] normals);
1243
1244 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataBuildSingle1"), SuppressUnmanagedCodeSecurity]
1245 public static extern void GeomTriMeshDataBuildSimple1(IntPtr d,
1246 IntPtr vertices, int vertexStride, int vertexCount,
1247 IntPtr indices, int indexCount, int triStride,
1248 IntPtr normals);
1249
1250 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshClearTCCache"), SuppressUnmanagedCodeSecurity]
1251 public static extern void GeomTriMeshClearTCCache(IntPtr g);
1252
1253 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataCreate"), SuppressUnmanagedCodeSecurity]
1254 public static extern IntPtr GeomTriMeshDataCreate();
1255
1256 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataDestroy"), SuppressUnmanagedCodeSecurity]
1257 public static extern void GeomTriMeshDataDestroy(IntPtr d);
1258
1259 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataGet"), SuppressUnmanagedCodeSecurity]
1260 public static extern IntPtr GeomTriMeshDataGet(IntPtr d, int data_id);
1261
1262 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataPreprocess"), SuppressUnmanagedCodeSecurity]
1263 public static extern void GeomTriMeshDataPreprocess(IntPtr d);
1264
1265 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataSet"), SuppressUnmanagedCodeSecurity]
1266 public static extern void GeomTriMeshDataSet(IntPtr d, int data_id, IntPtr in_data);
1267
1268 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshDataUpdate"), SuppressUnmanagedCodeSecurity]
1269 public static extern void GeomTriMeshDataUpdate(IntPtr d);
1270
1271 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshEnableTC"), SuppressUnmanagedCodeSecurity]
1272 public static extern void GeomTriMeshEnableTC(IntPtr g, int geomClass, bool enable);
1273
1274 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetArrayCallback"), SuppressUnmanagedCodeSecurity]
1275 public static extern TriArrayCallback GeomTriMeshGetArrayCallback(IntPtr g);
1276
1277 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetCallback"), SuppressUnmanagedCodeSecurity]
1278 public static extern TriCallback GeomTriMeshGetCallback(IntPtr g);
1279
1280 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetData"), SuppressUnmanagedCodeSecurity]
1281 public static extern IntPtr GeomTriMeshGetData(IntPtr g);
1282
1283 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetLastTransform"), SuppressUnmanagedCodeSecurity]
1284 public extern unsafe static Matrix4* GeomTriMeshGetLastTransformUnsafe(IntPtr geom);
1285 public static Matrix4 GeomTriMeshGetLastTransform(IntPtr geom)
1286 {
1287 unsafe { return *(GeomTriMeshGetLastTransformUnsafe(geom)); }
1288 }
1289
1290 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetPoint"), SuppressUnmanagedCodeSecurity]
1291 public extern static void GeomTriMeshGetPoint(IntPtr g, int index, dReal u, dReal v, ref Vector3 outVec);
1292
1293 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetRayCallback"), SuppressUnmanagedCodeSecurity]
1294 public static extern TriRayCallback GeomTriMeshGetRayCallback(IntPtr g);
1295
1296 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriangle"), SuppressUnmanagedCodeSecurity]
1297 public extern static void GeomTriMeshGetTriangle(IntPtr g, int index, ref Vector3 v0, ref Vector3 v1, ref Vector3 v2);
1298
1299 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriangleCount"), SuppressUnmanagedCodeSecurity]
1300 public extern static int GeomTriMeshGetTriangleCount(IntPtr g);
1301
1302 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshGetTriMeshDataID"), SuppressUnmanagedCodeSecurity]
1303 public static extern IntPtr GeomTriMeshGetTriMeshDataID(IntPtr g);
1304
1305 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshIsTCEnabled"), SuppressUnmanagedCodeSecurity]
1306 public static extern bool GeomTriMeshIsTCEnabled(IntPtr g, int geomClass);
1307
1308 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetArrayCallback"), SuppressUnmanagedCodeSecurity]
1309 public static extern void GeomTriMeshSetArrayCallback(IntPtr g, TriArrayCallback arrayCallback);
1310
1311 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetCallback"), SuppressUnmanagedCodeSecurity]
1312 public static extern void GeomTriMeshSetCallback(IntPtr g, TriCallback callback);
1313
1314 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetData"), SuppressUnmanagedCodeSecurity]
1315 public static extern void GeomTriMeshSetData(IntPtr g, IntPtr data);
1316
1317 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
1318 public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref Matrix4 last_trans);
1319
1320 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetLastTransform"), SuppressUnmanagedCodeSecurity]
1321 public static extern void GeomTriMeshSetLastTransform(IntPtr g, ref dReal M00);
1322
1323 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomTriMeshSetRayCallback"), SuppressUnmanagedCodeSecurity]
1324 public static extern void GeomTriMeshSetRayCallback(IntPtr g, TriRayCallback callback);
1325
1326 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGetConfiguration"), SuppressUnmanagedCodeSecurity]
1327 public static extern IntPtr iGetConfiguration();
1328
1329 public static string GetConfiguration()
1330 {
1331 IntPtr ptr = iGetConfiguration();
1332 string s = Marshal.PtrToStringAnsi(ptr);
1333 return s;
1334 }
1335
1336 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceCreate"), SuppressUnmanagedCodeSecurity]
1337 public static extern IntPtr HashSpaceCreate(IntPtr space);
1338
1339 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceGetLevels"), SuppressUnmanagedCodeSecurity]
1340 public static extern void HashSpaceGetLevels(IntPtr space, out int minlevel, out int maxlevel);
1341
1342 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceSetLevels"), SuppressUnmanagedCodeSecurity]
1343 public static extern void HashSpaceSetLevels(IntPtr space, int minlevel, int maxlevel);
1344
1345 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInfiniteAABB"), SuppressUnmanagedCodeSecurity]
1346 public static extern void InfiniteAABB(IntPtr geom, out AABB aabb);
1347
1348 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInitODE"), SuppressUnmanagedCodeSecurity]
1349 public static extern void InitODE();
1350
1351 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInitODE2"), SuppressUnmanagedCodeSecurity]
1352 public static extern int InitODE2(uint ODEInitFlags);
1353
1354 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dIsPositiveDefinite"), SuppressUnmanagedCodeSecurity]
1355 public static extern int IsPositiveDefinite(ref dReal A, int n);
1356
1357 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dInvertPDMatrix"), SuppressUnmanagedCodeSecurity]
1358 public static extern int InvertPDMatrix(ref dReal A, out dReal Ainv, int n);
1359
1360 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddAMotorTorques"), SuppressUnmanagedCodeSecurity]
1361 public static extern void JointAddAMotorTorques(IntPtr joint, dReal torque1, dReal torque2, dReal torque3);
1362
1363 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddHingeTorque"), SuppressUnmanagedCodeSecurity]
1364 public static extern void JointAddHingeTorque(IntPtr joint, dReal torque);
1365
1366 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddHinge2Torque"), SuppressUnmanagedCodeSecurity]
1367 public static extern void JointAddHinge2Torques(IntPtr joint, dReal torque1, dReal torque2);
1368
1369 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddPRTorque"), SuppressUnmanagedCodeSecurity]
1370 public static extern void JointAddPRTorque(IntPtr joint, dReal torque);
1371
1372 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddUniversalTorque"), SuppressUnmanagedCodeSecurity]
1373 public static extern void JointAddUniversalTorques(IntPtr joint, dReal torque1, dReal torque2);
1374
1375 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAddSliderForce"), SuppressUnmanagedCodeSecurity]
1376 public static extern void JointAddSliderForce(IntPtr joint, dReal force);
1377
1378 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointAttach"), SuppressUnmanagedCodeSecurity]
1379 public static extern void JointAttach(IntPtr joint, IntPtr body1, IntPtr body2);
1380
1381 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateAMotor"), SuppressUnmanagedCodeSecurity]
1382 public static extern IntPtr JointCreateAMotor(IntPtr world, IntPtr group);
1383
1384 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateBall"), SuppressUnmanagedCodeSecurity]
1385 public static extern IntPtr JointCreateBall(IntPtr world, IntPtr group);
1386
1387 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
1388 public static extern IntPtr JointCreateContact(IntPtr world, IntPtr group, ref Contact contact);
1389 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateContact"), SuppressUnmanagedCodeSecurity]
1390 public static extern IntPtr JointCreateContactPtr(IntPtr world, IntPtr group, IntPtr contact);
1391
1392 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateFixed"), SuppressUnmanagedCodeSecurity]
1393 public static extern IntPtr JointCreateFixed(IntPtr world, IntPtr group);
1394
1395 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateHinge"), SuppressUnmanagedCodeSecurity]
1396 public static extern IntPtr JointCreateHinge(IntPtr world, IntPtr group);
1397
1398 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateHinge2"), SuppressUnmanagedCodeSecurity]
1399 public static extern IntPtr JointCreateHinge2(IntPtr world, IntPtr group);
1400
1401 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateLMotor"), SuppressUnmanagedCodeSecurity]
1402 public static extern IntPtr JointCreateLMotor(IntPtr world, IntPtr group);
1403
1404 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateNull"), SuppressUnmanagedCodeSecurity]
1405 public static extern IntPtr JointCreateNull(IntPtr world, IntPtr group);
1406
1407 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreatePR"), SuppressUnmanagedCodeSecurity]
1408 public static extern IntPtr JointCreatePR(IntPtr world, IntPtr group);
1409
1410 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreatePlane2D"), SuppressUnmanagedCodeSecurity]
1411 public static extern IntPtr JointCreatePlane2D(IntPtr world, IntPtr group);
1412
1413 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateSlider"), SuppressUnmanagedCodeSecurity]
1414 public static extern IntPtr JointCreateSlider(IntPtr world, IntPtr group);
1415
1416 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointCreateUniversal"), SuppressUnmanagedCodeSecurity]
1417 public static extern IntPtr JointCreateUniversal(IntPtr world, IntPtr group);
1418
1419 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointDestroy"), SuppressUnmanagedCodeSecurity]
1420 public static extern void JointDestroy(IntPtr j);
1421
1422 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAngle"), SuppressUnmanagedCodeSecurity]
1423 public static extern dReal JointGetAMotorAngle(IntPtr j, int anum);
1424
1425 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAngleRate"), SuppressUnmanagedCodeSecurity]
1426 public static extern dReal JointGetAMotorAngleRate(IntPtr j, int anum);
1427
1428 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAxis"), SuppressUnmanagedCodeSecurity]
1429 public static extern void JointGetAMotorAxis(IntPtr j, int anum, out Vector3 result);
1430
1431 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorAxisRel"), SuppressUnmanagedCodeSecurity]
1432 public static extern int JointGetAMotorAxisRel(IntPtr j, int anum);
1433
1434 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorMode"), SuppressUnmanagedCodeSecurity]
1435 public static extern int JointGetAMotorMode(IntPtr j);
1436
1437 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1438 public static extern int JointGetAMotorNumAxes(IntPtr j);
1439
1440 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetAMotorParam"), SuppressUnmanagedCodeSecurity]
1441 public static extern dReal JointGetAMotorParam(IntPtr j, int parameter);
1442
1443 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBallAnchor"), SuppressUnmanagedCodeSecurity]
1444 public static extern void JointGetBallAnchor(IntPtr j, out Vector3 result);
1445
1446 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBallAnchor2"), SuppressUnmanagedCodeSecurity]
1447 public static extern void JointGetBallAnchor2(IntPtr j, out Vector3 result);
1448
1449 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetBody"), SuppressUnmanagedCodeSecurity]
1450 public static extern IntPtr JointGetBody(IntPtr j);
1451
1452 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetData"), SuppressUnmanagedCodeSecurity]
1453 public static extern IntPtr JointGetData(IntPtr j);
1454
1455 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetFeedback"), SuppressUnmanagedCodeSecurity]
1456 public extern unsafe static JointFeedback* JointGetFeedbackUnsafe(IntPtr j);
1457 public static JointFeedback JointGetFeedback(IntPtr j)
1458 {
1459 unsafe { return *(JointGetFeedbackUnsafe(j)); }
1460 }
1461
1462 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAnchor"), SuppressUnmanagedCodeSecurity]
1463 public static extern void JointGetHingeAnchor(IntPtr j, out Vector3 result);
1464
1465 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAngle"), SuppressUnmanagedCodeSecurity]
1466 public static extern dReal JointGetHingeAngle(IntPtr j);
1467
1468 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAngleRate"), SuppressUnmanagedCodeSecurity]
1469 public static extern dReal JointGetHingeAngleRate(IntPtr j);
1470
1471 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAxis"), SuppressUnmanagedCodeSecurity]
1472 public static extern void JointGetHingeAxis(IntPtr j, out Vector3 result);
1473
1474 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeParam"), SuppressUnmanagedCodeSecurity]
1475 public static extern dReal JointGetHingeParam(IntPtr j, int parameter);
1476
1477 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle1"), SuppressUnmanagedCodeSecurity]
1478 public static extern dReal JointGetHinge2Angle1(IntPtr j);
1479
1480 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle1Rate"), SuppressUnmanagedCodeSecurity]
1481 public static extern dReal JointGetHinge2Angle1Rate(IntPtr j);
1482
1483 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Angle2Rate"), SuppressUnmanagedCodeSecurity]
1484 public static extern dReal JointGetHinge2Angle2Rate(IntPtr j);
1485
1486 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHingeAnchor2"), SuppressUnmanagedCodeSecurity]
1487 public static extern void JointGetHingeAnchor2(IntPtr j, out Vector3 result);
1488
1489 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
1490 public static extern void JointGetHinge2Anchor(IntPtr j, out Vector3 result);
1491
1492 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Anchor2"), SuppressUnmanagedCodeSecurity]
1493 public static extern void JointGetHinge2Anchor2(IntPtr j, out Vector3 result);
1494
1495 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
1496 public static extern void JointGetHinge2Axis1(IntPtr j, out Vector3 result);
1497
1498 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
1499 public static extern void JointGetHinge2Axis2(IntPtr j, out Vector3 result);
1500
1501 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetHinge2Param"), SuppressUnmanagedCodeSecurity]
1502 public static extern dReal JointGetHinge2Param(IntPtr j, int parameter);
1503
1504 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorAxis"), SuppressUnmanagedCodeSecurity]
1505 public static extern void JointGetLMotorAxis(IntPtr j, int anum, out Vector3 result);
1506
1507 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1508 public static extern int JointGetLMotorNumAxes(IntPtr j);
1509
1510 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetLMotorParam"), SuppressUnmanagedCodeSecurity]
1511 public static extern dReal JointGetLMotorParam(IntPtr j, int parameter);
1512
1513 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAnchor"), SuppressUnmanagedCodeSecurity]
1514 public static extern void JointGetPRAnchor(IntPtr j, out Vector3 result);
1515
1516 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAxis1"), SuppressUnmanagedCodeSecurity]
1517 public static extern void JointGetPRAxis1(IntPtr j, out Vector3 result);
1518
1519 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRAxis2"), SuppressUnmanagedCodeSecurity]
1520 public static extern void JointGetPRAxis2(IntPtr j, out Vector3 result);
1521
1522 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRParam"), SuppressUnmanagedCodeSecurity]
1523 public static extern dReal JointGetPRParam(IntPtr j, int parameter);
1524
1525 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRPosition"), SuppressUnmanagedCodeSecurity]
1526 public static extern dReal JointGetPRPosition(IntPtr j);
1527
1528 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetPRPositionRate"), SuppressUnmanagedCodeSecurity]
1529 public static extern dReal JointGetPRPositionRate(IntPtr j);
1530
1531 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderAxis"), SuppressUnmanagedCodeSecurity]
1532 public static extern void JointGetSliderAxis(IntPtr j, out Vector3 result);
1533
1534 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderParam"), SuppressUnmanagedCodeSecurity]
1535 public static extern dReal JointGetSliderParam(IntPtr j, int parameter);
1536
1537 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderPosition"), SuppressUnmanagedCodeSecurity]
1538 public static extern dReal JointGetSliderPosition(IntPtr j);
1539
1540 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetSliderPositionRate"), SuppressUnmanagedCodeSecurity]
1541 public static extern dReal JointGetSliderPositionRate(IntPtr j);
1542
1543 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetType"), SuppressUnmanagedCodeSecurity]
1544 public static extern JointType JointGetType(IntPtr j);
1545
1546 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
1547 public static extern void JointGetUniversalAnchor(IntPtr j, out Vector3 result);
1548
1549 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAnchor2"), SuppressUnmanagedCodeSecurity]
1550 public static extern void JointGetUniversalAnchor2(IntPtr j, out Vector3 result);
1551
1552 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle1"), SuppressUnmanagedCodeSecurity]
1553 public static extern dReal JointGetUniversalAngle1(IntPtr j);
1554
1555 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle1Rate"), SuppressUnmanagedCodeSecurity]
1556 public static extern dReal JointGetUniversalAngle1Rate(IntPtr j);
1557
1558 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle2"), SuppressUnmanagedCodeSecurity]
1559 public static extern dReal JointGetUniversalAngle2(IntPtr j);
1560
1561 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngle2Rate"), SuppressUnmanagedCodeSecurity]
1562 public static extern dReal JointGetUniversalAngle2Rate(IntPtr j);
1563
1564 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAngles"), SuppressUnmanagedCodeSecurity]
1565 public static extern void JointGetUniversalAngles(IntPtr j, out dReal angle1, out dReal angle2);
1566
1567 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
1568 public static extern void JointGetUniversalAxis1(IntPtr j, out Vector3 result);
1569
1570 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
1571 public static extern void JointGetUniversalAxis2(IntPtr j, out Vector3 result);
1572
1573 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGetUniversalParam"), SuppressUnmanagedCodeSecurity]
1574 public static extern dReal JointGetUniversalParam(IntPtr j, int parameter);
1575
1576 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupCreate"), SuppressUnmanagedCodeSecurity]
1577 public static extern IntPtr JointGroupCreate(int max_size);
1578
1579 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupDestroy"), SuppressUnmanagedCodeSecurity]
1580 public static extern void JointGroupDestroy(IntPtr group);
1581
1582 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointGroupEmpty"), SuppressUnmanagedCodeSecurity]
1583 public static extern void JointGroupEmpty(IntPtr group);
1584
1585 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorAngle"), SuppressUnmanagedCodeSecurity]
1586 public static extern void JointSetAMotorAngle(IntPtr j, int anum, dReal angle);
1587
1588 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorAxis"), SuppressUnmanagedCodeSecurity]
1589 public static extern void JointSetAMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
1590
1591 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorMode"), SuppressUnmanagedCodeSecurity]
1592 public static extern void JointSetAMotorMode(IntPtr j, int mode);
1593
1594 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1595 public static extern void JointSetAMotorNumAxes(IntPtr group, int num);
1596
1597 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetAMotorParam"), SuppressUnmanagedCodeSecurity]
1598 public static extern void JointSetAMotorParam(IntPtr group, int parameter, dReal value);
1599
1600 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetBallAnchor"), SuppressUnmanagedCodeSecurity]
1601 public static extern void JointSetBallAnchor(IntPtr j, dReal x, dReal y, dReal z);
1602
1603 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetBallAnchor2"), SuppressUnmanagedCodeSecurity]
1604 public static extern void JointSetBallAnchor2(IntPtr j, dReal x, dReal y, dReal z);
1605
1606 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetData"), SuppressUnmanagedCodeSecurity]
1607 public static extern void JointSetData(IntPtr j, IntPtr data);
1608
1609 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetFeedback"), SuppressUnmanagedCodeSecurity]
1610 public static extern void JointSetFeedback(IntPtr j, out JointFeedback feedback);
1611
1612 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetFixed"), SuppressUnmanagedCodeSecurity]
1613 public static extern void JointSetFixed(IntPtr j);
1614
1615 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAnchor"), SuppressUnmanagedCodeSecurity]
1616 public static extern void JointSetHingeAnchor(IntPtr j, dReal x, dReal y, dReal z);
1617
1618 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAnchorDelta"), SuppressUnmanagedCodeSecurity]
1619 public static extern void JointSetHingeAnchorDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
1620
1621 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeAxis"), SuppressUnmanagedCodeSecurity]
1622 public static extern void JointSetHingeAxis(IntPtr j, dReal x, dReal y, dReal z);
1623
1624 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHingeParam"), SuppressUnmanagedCodeSecurity]
1625 public static extern void JointSetHingeParam(IntPtr j, int parameter, dReal value);
1626
1627 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Anchor"), SuppressUnmanagedCodeSecurity]
1628 public static extern void JointSetHinge2Anchor(IntPtr j, dReal x, dReal y, dReal z);
1629
1630 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Axis1"), SuppressUnmanagedCodeSecurity]
1631 public static extern void JointSetHinge2Axis1(IntPtr j, dReal x, dReal y, dReal z);
1632
1633 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Axis2"), SuppressUnmanagedCodeSecurity]
1634 public static extern void JointSetHinge2Axis2(IntPtr j, dReal x, dReal y, dReal z);
1635
1636 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetHinge2Param"), SuppressUnmanagedCodeSecurity]
1637 public static extern void JointSetHinge2Param(IntPtr j, int parameter, dReal value);
1638
1639 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorAxis"), SuppressUnmanagedCodeSecurity]
1640 public static extern void JointSetLMotorAxis(IntPtr j, int anum, int rel, dReal x, dReal y, dReal z);
1641
1642 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorNumAxes"), SuppressUnmanagedCodeSecurity]
1643 public static extern void JointSetLMotorNumAxes(IntPtr j, int num);
1644
1645 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetLMotorParam"), SuppressUnmanagedCodeSecurity]
1646 public static extern void JointSetLMotorParam(IntPtr j, int parameter, dReal value);
1647
1648 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DAngleParam"), SuppressUnmanagedCodeSecurity]
1649 public static extern void JointSetPlane2DAngleParam(IntPtr j, int parameter, dReal value);
1650
1651 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DXParam"), SuppressUnmanagedCodeSecurity]
1652 public static extern void JointSetPlane2DXParam(IntPtr j, int parameter, dReal value);
1653
1654 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPlane2DYParam"), SuppressUnmanagedCodeSecurity]
1655 public static extern void JointSetPlane2DYParam(IntPtr j, int parameter, dReal value);
1656
1657 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAnchor"), SuppressUnmanagedCodeSecurity]
1658 public static extern void JointSetPRAnchor(IntPtr j, dReal x, dReal y, dReal z);
1659
1660 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAxis1"), SuppressUnmanagedCodeSecurity]
1661 public static extern void JointSetPRAxis1(IntPtr j, dReal x, dReal y, dReal z);
1662
1663 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRAxis2"), SuppressUnmanagedCodeSecurity]
1664 public static extern void JointSetPRAxis2(IntPtr j, dReal x, dReal y, dReal z);
1665
1666 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetPRParam"), SuppressUnmanagedCodeSecurity]
1667 public static extern void JointSetPRParam(IntPtr j, int parameter, dReal value);
1668
1669 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderAxis"), SuppressUnmanagedCodeSecurity]
1670 public static extern void JointSetSliderAxis(IntPtr j, dReal x, dReal y, dReal z);
1671
1672 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderAxisDelta"), SuppressUnmanagedCodeSecurity]
1673 public static extern void JointSetSliderAxisDelta(IntPtr j, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az);
1674
1675 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetSliderParam"), SuppressUnmanagedCodeSecurity]
1676 public static extern void JointSetSliderParam(IntPtr j, int parameter, dReal value);
1677
1678 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAnchor"), SuppressUnmanagedCodeSecurity]
1679 public static extern void JointSetUniversalAnchor(IntPtr j, dReal x, dReal y, dReal z);
1680
1681 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAxis1"), SuppressUnmanagedCodeSecurity]
1682 public static extern void JointSetUniversalAxis1(IntPtr j, dReal x, dReal y, dReal z);
1683
1684 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalAxis2"), SuppressUnmanagedCodeSecurity]
1685 public static extern void JointSetUniversalAxis2(IntPtr j, dReal x, dReal y, dReal z);
1686
1687 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dJointSetUniversalParam"), SuppressUnmanagedCodeSecurity]
1688 public static extern void JointSetUniversalParam(IntPtr j, int parameter, dReal value);
1689
1690 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dLDLTAddTL"), SuppressUnmanagedCodeSecurity]
1691 public static extern void LDLTAddTL(ref dReal L, ref dReal d, ref dReal a, int n, int nskip);
1692
1693 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassAdd"), SuppressUnmanagedCodeSecurity]
1694 public static extern void MassAdd(ref Mass a, ref Mass b);
1695
1696 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassAdjust"), SuppressUnmanagedCodeSecurity]
1697 public static extern void MassAdjust(ref Mass m, dReal newmass);
1698
1699 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassCheck"), SuppressUnmanagedCodeSecurity]
1700 public static extern bool MassCheck(ref Mass m);
1701
1702 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
1703 public static extern void MassRotate(ref Mass mass, ref Matrix3 R);
1704
1705 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassRotate"), SuppressUnmanagedCodeSecurity]
1706 public static extern void MassRotate(ref Mass mass, ref dReal M00);
1707
1708 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetBox"), SuppressUnmanagedCodeSecurity]
1709 public static extern void MassSetBox(out Mass mass, dReal density, dReal lx, dReal ly, dReal lz);
1710
1711 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetBoxTotal"), SuppressUnmanagedCodeSecurity]
1712 public static extern void MassSetBoxTotal(out Mass mass, dReal total_mass, dReal lx, dReal ly, dReal lz);
1713
1714 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCapsule"), SuppressUnmanagedCodeSecurity]
1715 public static extern void MassSetCapsule(out Mass mass, dReal density, int direction, dReal radius, dReal length);
1716
1717 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCapsuleTotal"), SuppressUnmanagedCodeSecurity]
1718 public static extern void MassSetCapsuleTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
1719
1720 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCylinder"), SuppressUnmanagedCodeSecurity]
1721 public static extern void MassSetCylinder(out Mass mass, dReal density, int direction, dReal radius, dReal length);
1722
1723 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetCylinderTotal"), SuppressUnmanagedCodeSecurity]
1724 public static extern void MassSetCylinderTotal(out Mass mass, dReal total_mass, int direction, dReal radius, dReal length);
1725
1726 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetParameters"), SuppressUnmanagedCodeSecurity]
1727 public static extern void MassSetParameters(out Mass mass, dReal themass,
1728 dReal cgx, dReal cgy, dReal cgz,
1729 dReal i11, dReal i22, dReal i33,
1730 dReal i12, dReal i13, dReal i23);
1731
1732 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetSphere"), SuppressUnmanagedCodeSecurity]
1733 public static extern void MassSetSphere(out Mass mass, dReal density, dReal radius);
1734
1735 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetSphereTotal"), SuppressUnmanagedCodeSecurity]
1736 public static extern void dMassSetSphereTotal(out Mass mass, dReal total_mass, dReal radius);
1737
1738 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetTrimesh"), SuppressUnmanagedCodeSecurity]
1739 public static extern void MassSetTrimesh(out Mass mass, dReal density, IntPtr g);
1740
1741 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassSetZero"), SuppressUnmanagedCodeSecurity]
1742 public static extern void MassSetZero(out Mass mass);
1743
1744 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMassTranslate"), SuppressUnmanagedCodeSecurity]
1745 public static extern void MassTranslate(ref Mass mass, dReal x, dReal y, dReal z);
1746
1747 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
1748 public static extern void Multiply0(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1749
1750 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply0"), SuppressUnmanagedCodeSecurity]
1751 private static extern void MultiplyiM3V3(out Vector3 vout, ref Matrix3 matrix, ref Vector3 vect,int p, int q, int r);
1752 public static void MultiplyM3V3(out Vector3 outvector, ref Matrix3 matrix, ref Vector3 invector)
1753 {
1754 MultiplyiM3V3(out outvector, ref matrix, ref invector, 3, 3, 1);
1755 }
1756
1757 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply1"), SuppressUnmanagedCodeSecurity]
1758 public static extern void Multiply1(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1759
1760 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dMultiply2"), SuppressUnmanagedCodeSecurity]
1761 public static extern void Multiply2(out dReal A00, ref dReal B00, ref dReal C00, int p, int q, int r);
1762
1763 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
1764 public static extern void QFromAxisAndAngle(out Quaternion q, dReal ax, dReal ay, dReal az, dReal angle);
1765
1766 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQfromR"), SuppressUnmanagedCodeSecurity]
1767 public static extern void QfromR(out Quaternion q, ref Matrix3 R);
1768
1769 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply0"), SuppressUnmanagedCodeSecurity]
1770 public static extern void QMultiply0(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1771
1772 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply1"), SuppressUnmanagedCodeSecurity]
1773 public static extern void QMultiply1(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1774
1775 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply2"), SuppressUnmanagedCodeSecurity]
1776 public static extern void QMultiply2(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1777
1778 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQMultiply3"), SuppressUnmanagedCodeSecurity]
1779 public static extern void QMultiply3(out Quaternion qa, ref Quaternion qb, ref Quaternion qc);
1780
1781 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQSetIdentity"), SuppressUnmanagedCodeSecurity]
1782 public static extern void QSetIdentity(out Quaternion q);
1783
1784 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
1785 public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref Vector3 center, ref Vector3 extents, int depth);
1786
1787 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dQuadTreeSpaceCreate"), SuppressUnmanagedCodeSecurity]
1788 public static extern IntPtr QuadTreeSpaceCreate(IntPtr space, ref dReal centerX, ref dReal extentsX, int depth);
1789
1790 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRandReal"), SuppressUnmanagedCodeSecurity]
1791 public static extern dReal RandReal();
1792
1793 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFrom2Axes"), SuppressUnmanagedCodeSecurity]
1794 public static extern void RFrom2Axes(out Matrix3 R, dReal ax, dReal ay, dReal az, dReal bx, dReal by, dReal bz);
1795
1796 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromAxisAndAngle"), SuppressUnmanagedCodeSecurity]
1797 public static extern void RFromAxisAndAngle(out Matrix3 R, dReal x, dReal y, dReal z, dReal angle);
1798
1799 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromEulerAngles"), SuppressUnmanagedCodeSecurity]
1800 public static extern void RFromEulerAngles(out Matrix3 R, dReal phi, dReal theta, dReal psi);
1801
1802 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRfromQ"), SuppressUnmanagedCodeSecurity]
1803 public static extern void RfromQ(out Matrix3 R, ref Quaternion q);
1804
1805 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRFromZAxis"), SuppressUnmanagedCodeSecurity]
1806 public static extern void RFromZAxis(out Matrix3 R, dReal ax, dReal ay, dReal az);
1807
1808 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dRSetIdentity"), SuppressUnmanagedCodeSecurity]
1809 public static extern void RSetIdentity(out Matrix3 R);
1810
1811 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSetValue"), SuppressUnmanagedCodeSecurity]
1812 public static extern void SetValue(out dReal a, int n);
1813
1814 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSetZero"), SuppressUnmanagedCodeSecurity]
1815 public static extern void SetZero(out dReal a, int n);
1816
1817 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSimpleSpaceCreate"), SuppressUnmanagedCodeSecurity]
1818 public static extern IntPtr SimpleSpaceCreate(IntPtr space);
1819
1820 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveCholesky"), SuppressUnmanagedCodeSecurity]
1821 public static extern void SolveCholesky(ref dReal L, out dReal b, int n);
1822
1823 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveL1"), SuppressUnmanagedCodeSecurity]
1824 public static extern void SolveL1(ref dReal L, out dReal b, int n, int nskip);
1825
1826 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveL1T"), SuppressUnmanagedCodeSecurity]
1827 public static extern void SolveL1T(ref dReal L, out dReal b, int n, int nskip);
1828
1829 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSolveLDLT"), SuppressUnmanagedCodeSecurity]
1830 public static extern void SolveLDLT(ref dReal L, ref dReal d, out dReal b, int n, int nskip);
1831
1832 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceAdd"), SuppressUnmanagedCodeSecurity]
1833 public static extern void SpaceAdd(IntPtr space, IntPtr geom);
1834
1835 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceLockQuery"), SuppressUnmanagedCodeSecurity]
1836 public static extern bool SpaceLockQuery(IntPtr space);
1837
1838 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceClean"), SuppressUnmanagedCodeSecurity]
1839 public static extern void SpaceClean(IntPtr space);
1840
1841 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceCollide"), SuppressUnmanagedCodeSecurity]
1842 public static extern void SpaceCollide(IntPtr space, IntPtr data, NearCallback callback);
1843
1844 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceCollide2"), SuppressUnmanagedCodeSecurity]
1845 public static extern void SpaceCollide2(IntPtr space1, IntPtr space2, IntPtr data, NearCallback callback);
1846
1847 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceDestroy"), SuppressUnmanagedCodeSecurity]
1848 public static extern void SpaceDestroy(IntPtr space);
1849
1850 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetCleanup"), SuppressUnmanagedCodeSecurity]
1851 public static extern bool SpaceGetCleanup(IntPtr space);
1852
1853 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetNumGeoms"), SuppressUnmanagedCodeSecurity]
1854 public static extern int SpaceGetNumGeoms(IntPtr space);
1855
1856 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetGeom"), SuppressUnmanagedCodeSecurity]
1857 public static extern IntPtr SpaceGetGeom(IntPtr space, int i);
1858
1859 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceGetSublevel"), SuppressUnmanagedCodeSecurity]
1860 public static extern int SpaceGetSublevel(IntPtr space);
1861
1862 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceQuery"), SuppressUnmanagedCodeSecurity]
1863 public static extern bool SpaceQuery(IntPtr space, IntPtr geom);
1864
1865 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceRemove"), SuppressUnmanagedCodeSecurity]
1866 public static extern void SpaceRemove(IntPtr space, IntPtr geom);
1867
1868 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceSetCleanup"), SuppressUnmanagedCodeSecurity]
1869 public static extern void SpaceSetCleanup(IntPtr space, bool mode);
1870
1871 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSpaceSetSublevel"), SuppressUnmanagedCodeSecurity]
1872 public static extern void SpaceSetSublevel(IntPtr space, int sublevel);
1873
1874 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dSweepAndPruneSpaceCreate"), SuppressUnmanagedCodeSecurity]
1875 public static extern IntPtr SweepAndPruneSpaceCreate(IntPtr space, int AxisOrder);
1876
1877 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dVectorScale"), SuppressUnmanagedCodeSecurity]
1878 public static extern void VectorScale(out dReal a, ref dReal d, int n);
1879
1880 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldCreate"), SuppressUnmanagedCodeSecurity]
1881 public static extern IntPtr WorldCreate();
1882
1883 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldDestroy"), SuppressUnmanagedCodeSecurity]
1884 public static extern void WorldDestroy(IntPtr world);
1885
1886 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableAverageSamplesCount"), SuppressUnmanagedCodeSecurity]
1887 public static extern int WorldGetAutoDisableAverageSamplesCount(IntPtr world);
1888
1889 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
1890 public static extern dReal WorldGetAutoDisableAngularThreshold(IntPtr world);
1891
1892 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
1893 public static extern bool WorldGetAutoDisableFlag(IntPtr world);
1894
1895 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
1896 public static extern dReal WorldGetAutoDisableLinearThreshold(IntPtr world);
1897
1898 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
1899 public static extern int WorldGetAutoDisableSteps(IntPtr world);
1900
1901 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
1902 public static extern dReal WorldGetAutoDisableTime(IntPtr world);
1903
1904 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
1905 public static extern int WorldGetAutoEnableDepthSF1(IntPtr world);
1906
1907 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetCFM"), SuppressUnmanagedCodeSecurity]
1908 public static extern dReal WorldGetCFM(IntPtr world);
1909
1910 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetERP"), SuppressUnmanagedCodeSecurity]
1911 public static extern dReal WorldGetERP(IntPtr world);
1912
1913 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
1914 public static extern void WorldGetGravity(IntPtr world, out Vector3 gravity);
1915
1916 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetGravity"), SuppressUnmanagedCodeSecurity]
1917 public static extern void WorldGetGravity(IntPtr world, out dReal X);
1918
1919 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
1920 public static extern dReal WorldGetContactMaxCorrectingVel(IntPtr world);
1921
1922 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
1923 public static extern dReal WorldGetContactSurfaceLayer(IntPtr world);
1924
1925 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAngularDamping"), SuppressUnmanagedCodeSecurity]
1926 public static extern dReal WorldGetAngularDamping(IntPtr world);
1927
1928 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
1929 public static extern dReal WorldGetAngularDampingThreshold(IntPtr world);
1930
1931 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetLinearDamping"), SuppressUnmanagedCodeSecurity]
1932 public static extern dReal WorldGetLinearDamping(IntPtr world);
1933
1934 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
1935 public static extern dReal WorldGetLinearDampingThreshold(IntPtr world);
1936
1937 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
1938 public static extern int WorldGetQuickStepNumIterations(IntPtr world);
1939
1940 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetQuickStepW"), SuppressUnmanagedCodeSecurity]
1941 public static extern dReal WorldGetQuickStepW(IntPtr world);
1942
1943 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldGetMaxAngularSpeed"), SuppressUnmanagedCodeSecurity]
1944 public static extern dReal WorldGetMaxAngularSpeed(IntPtr world);
1945
1946 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
1947 public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out Vector3 force);
1948
1949 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldImpulseToForce"), SuppressUnmanagedCodeSecurity]
1950 public static extern void WorldImpulseToForce(IntPtr world, dReal stepsize, dReal ix, dReal iy, dReal iz, out dReal forceX);
1951
1952 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldQuickStep"), SuppressUnmanagedCodeSecurity]
1953 public static extern void WorldQuickStep(IntPtr world, dReal stepsize);
1954
1955 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAngularDamping"), SuppressUnmanagedCodeSecurity]
1956 public static extern void WorldSetAngularDamping(IntPtr world, dReal scale);
1957
1958 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAngularDampingThreshold"), SuppressUnmanagedCodeSecurity]
1959 public static extern void WorldSetAngularDampingThreshold(IntPtr world, dReal threshold);
1960
1961 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableAngularThreshold"), SuppressUnmanagedCodeSecurity]
1962 public static extern void WorldSetAutoDisableAngularThreshold(IntPtr world, dReal angular_threshold);
1963
1964 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableAverageSamplesCount"), SuppressUnmanagedCodeSecurity]
1965 public static extern void WorldSetAutoDisableAverageSamplesCount(IntPtr world, int average_samples_count);
1966
1967 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableFlag"), SuppressUnmanagedCodeSecurity]
1968 public static extern void WorldSetAutoDisableFlag(IntPtr world, bool do_auto_disable);
1969
1970 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableLinearThreshold"), SuppressUnmanagedCodeSecurity]
1971 public static extern void WorldSetAutoDisableLinearThreshold(IntPtr world, dReal linear_threshold);
1972
1973 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableSteps"), SuppressUnmanagedCodeSecurity]
1974 public static extern void WorldSetAutoDisableSteps(IntPtr world, int steps);
1975
1976 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoDisableTime"), SuppressUnmanagedCodeSecurity]
1977 public static extern void WorldSetAutoDisableTime(IntPtr world, dReal time);
1978
1979 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetAutoEnableDepthSF1"), SuppressUnmanagedCodeSecurity]
1980 public static extern void WorldSetAutoEnableDepthSF1(IntPtr world, int autoEnableDepth);
1981
1982 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetCFM"), SuppressUnmanagedCodeSecurity]
1983 public static extern void WorldSetCFM(IntPtr world, dReal cfm);
1984
1985 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetContactMaxCorrectingVel"), SuppressUnmanagedCodeSecurity]
1986 public static extern void WorldSetContactMaxCorrectingVel(IntPtr world, dReal vel);
1987
1988 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetContactSurfaceLayer"), SuppressUnmanagedCodeSecurity]
1989 public static extern void WorldSetContactSurfaceLayer(IntPtr world, dReal depth);
1990
1991 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetDamping"), SuppressUnmanagedCodeSecurity]
1992 public static extern void WorldSetDamping(IntPtr world, dReal linear_scale, dReal angular_scale);
1993
1994 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetERP"), SuppressUnmanagedCodeSecurity]
1995 public static extern void WorldSetERP(IntPtr world, dReal erp);
1996
1997 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetGravity"), SuppressUnmanagedCodeSecurity]
1998 public static extern void WorldSetGravity(IntPtr world, dReal x, dReal y, dReal z);
1999
2000 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetLinearDamping"), SuppressUnmanagedCodeSecurity]
2001 public static extern void WorldSetLinearDamping(IntPtr world, dReal scale);
2002
2003 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetLinearDampingThreshold"), SuppressUnmanagedCodeSecurity]
2004 public static extern void WorldSetLinearDampingThreshold(IntPtr world, dReal threshold);
2005
2006 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetQuickStepNumIterations"), SuppressUnmanagedCodeSecurity]
2007 public static extern void WorldSetQuickStepNumIterations(IntPtr world, int num);
2008
2009 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetQuickStepW"), SuppressUnmanagedCodeSecurity]
2010 public static extern void WorldSetQuickStepW(IntPtr world, dReal over_relaxation);
2011
2012 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldSetMaxAngularSpeed"), SuppressUnmanagedCodeSecurity]
2013 public static extern void WorldSetMaxAngularSpeed(IntPtr world, dReal max_speed);
2014
2015 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldStep"), SuppressUnmanagedCodeSecurity]
2016 public static extern void WorldStep(IntPtr world, dReal stepsize);
2017
2018 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldStepFast1"), SuppressUnmanagedCodeSecurity]
2019 public static extern void WorldStepFast1(IntPtr world, dReal stepsize, int maxiterations);
2020
2021 [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dWorldExportDIF"), SuppressUnmanagedCodeSecurity]
2022 public static extern void WorldExportDIF(IntPtr world, string filename, bool append, string prefix);
2023 }
2024}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs
new file mode 100644
index 0000000..55619c0
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs
@@ -0,0 +1,1978 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28
29// Revision by Ubit 2011/12
30
31using System;
32using System.Collections.Generic;
33using System.Reflection;
34using OpenMetaverse;
35using OdeAPI;
36using OpenSim.Framework;
37using OpenSim.Region.PhysicsModules.SharedBase;
38using log4net;
39
40namespace OpenSim.Region.PhysicsModule.ubOde
41{
42 /// <summary>
43 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
44 /// </summary>
45
46 public enum dParam : int
47 {
48 LowStop = 0,
49 HiStop = 1,
50 Vel = 2,
51 FMax = 3,
52 FudgeFactor = 4,
53 Bounce = 5,
54 CFM = 6,
55 StopERP = 7,
56 StopCFM = 8,
57 LoStop2 = 256,
58 HiStop2 = 257,
59 Vel2 = 258,
60 FMax2 = 259,
61 StopERP2 = 7 + 256,
62 StopCFM2 = 8 + 256,
63 LoStop3 = 512,
64 HiStop3 = 513,
65 Vel3 = 514,
66 FMax3 = 515,
67 StopERP3 = 7 + 512,
68 StopCFM3 = 8 + 512
69 }
70
71 public class OdeCharacter : PhysicsActor
72 {
73 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74
75 private Vector3 _position;
76 private Vector3 _zeroPosition;
77 private Vector3 _velocity;
78 private Vector3 _target_velocity;
79 private Vector3 _acceleration;
80 private Vector3 m_rotationalVelocity;
81 private Vector3 m_size;
82 private Vector3 m_collideNormal;
83 private Quaternion m_orientation;
84 private Quaternion m_orientation2D;
85 private float m_mass = 80f;
86 public float m_density = 60f;
87 private bool m_pidControllerActive = true;
88
89 const float basePID_D = 0.55f; // scaled for unit mass unit time (2200 /(50*80))
90 const float basePID_P = 0.225f; // scaled for unit mass unit time (900 /(50*80))
91 public float PID_D;
92 public float PID_P;
93
94 private float timeStep;
95 private float invtimeStep;
96
97 private float m_feetOffset = 0;
98 private float feetOff = 0;
99 private float boneOff = 0;
100 private float AvaAvaSizeXsq = 0.3f;
101 private float AvaAvaSizeYsq = 0.2f;
102
103 public float walkDivisor = 1.3f;
104 public float runDivisor = 0.8f;
105 private bool flying = false;
106 private bool m_iscolliding = false;
107 private bool m_iscollidingGround = false;
108 private bool m_iscollidingObj = false;
109 private bool m_alwaysRun = false;
110
111 private bool _zeroFlag = false;
112
113
114 private uint m_localID = 0;
115 public bool m_returnCollisions = false;
116 // taints and their non-tainted counterparts
117 public bool m_isPhysical = false; // the current physical status
118 public float MinimumGroundFlightOffset = 3f;
119
120 private float m_buoyancy = 0f;
121
122 private bool m_freemove = false;
123 // private CollisionLocker ode;
124
125// private string m_name = String.Empty;
126 // other filter control
127 int m_colliderfilter = 0;
128 int m_colliderGroundfilter = 0;
129 int m_colliderObjectfilter = 0;
130
131 // Default we're a Character
132 private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
133
134 // Default, Collide with Other Geometries, spaces, bodies and characters.
135 private CollisionCategories m_collisionFlags = (CollisionCategories.Character
136 | CollisionCategories.Geom
137 | CollisionCategories.VolumeDtc
138 );
139 // we do land collisions not ode | CollisionCategories.Land);
140 public IntPtr Body = IntPtr.Zero;
141 private ODEScene _parent_scene;
142 private IntPtr capsule = IntPtr.Zero;
143 public IntPtr collider = IntPtr.Zero;
144
145 public IntPtr Amotor = IntPtr.Zero;
146
147 public d.Mass ShellMass;
148
149 public int m_eventsubscription = 0;
150 private int m_cureventsubscription = 0;
151 private CollisionEventUpdate CollisionEventsThisFrame = null;
152 private bool SentEmptyCollisionsEvent;
153
154 // unique UUID of this character object
155 public UUID m_uuid;
156 public bool bad = false;
157
158 float mu;
159
160 // HoverHeight control
161 private float m_PIDHoverHeight;
162 private float m_PIDHoverTau;
163 private bool m_useHoverPID;
164 private PIDHoverType m_PIDHoverType;
165 private float m_targetHoverHeight;
166
167
168 public OdeCharacter(uint localID, String avName, ODEScene parent_scene, Vector3 pos, Vector3 pSize, float pfeetOffset, float density, float walk_divisor, float rundivisor)
169 {
170 m_uuid = UUID.Random();
171 m_localID = localID;
172
173 timeStep = parent_scene.ODE_STEPSIZE;
174 invtimeStep = 1 / timeStep;
175
176 if (pos.IsFinite())
177 {
178 if (pos.Z > 99999f)
179 {
180 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
181 }
182 if (pos.Z < -100f) // shouldn't this be 0 ?
183 {
184 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
185 }
186 _position = pos;
187 }
188 else
189 {
190 _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
191 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create");
192 }
193
194 _parent_scene = parent_scene;
195
196
197 m_size.X = pSize.X;
198 m_size.Y = pSize.Y;
199 m_size.Z = pSize.Z;
200
201 if(m_size.X <0.01f)
202 m_size.X = 0.01f;
203 if(m_size.Y <0.01f)
204 m_size.Y = 0.01f;
205 if(m_size.Z <0.01f)
206 m_size.Z = 0.01f;
207
208 m_feetOffset = pfeetOffset;
209 m_orientation = Quaternion.Identity;
210 m_orientation2D = Quaternion.Identity;
211 m_density = density;
212
213 // force lower density for testing
214 m_density = 3.0f;
215
216 mu = parent_scene.AvatarFriction;
217
218 walkDivisor = walk_divisor;
219 runDivisor = rundivisor;
220
221 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default
222
223 PID_D = basePID_D * m_mass * invtimeStep;
224 PID_P = basePID_P * m_mass * invtimeStep;
225
226 m_isPhysical = false; // current status: no ODE information exists
227
228 Name = avName;
229
230 AddChange(changes.Add, null);
231 }
232
233 public override int PhysicsActorType
234 {
235 get { return (int)ActorTypes.Agent; }
236 set { return; }
237 }
238
239 public override void getContactData(ref ContactData cdata)
240 {
241 cdata.mu = mu;
242 cdata.bounce = 0;
243 cdata.softcolide = false;
244 }
245
246 public override bool Building { get; set; }
247
248 /// <summary>
249 /// If this is set, the avatar will move faster
250 /// </summary>
251 public override bool SetAlwaysRun
252 {
253 get { return m_alwaysRun; }
254 set { m_alwaysRun = value; }
255 }
256
257 public override uint LocalID
258 {
259 get { return m_localID; }
260 set { m_localID = value; }
261 }
262
263 public override PhysicsActor ParentActor
264 {
265 get { return (PhysicsActor)this; }
266 }
267
268 public override bool Grabbed
269 {
270 set { return; }
271 }
272
273 public override bool Selected
274 {
275 set { return; }
276 }
277
278 public override float Buoyancy
279 {
280 get { return m_buoyancy; }
281 set { m_buoyancy = value; }
282 }
283
284 public override bool FloatOnWater
285 {
286 set { return; }
287 }
288
289 public override bool IsPhysical
290 {
291 get { return m_isPhysical; }
292 set { return; }
293 }
294
295 public override bool ThrottleUpdates
296 {
297 get { return false; }
298 set { return; }
299 }
300
301 public override bool Flying
302 {
303 get { return flying; }
304 set
305 {
306 flying = value;
307// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
308 }
309 }
310
311 /// <summary>
312 /// Returns if the avatar is colliding in general.
313 /// This includes the ground and objects and avatar.
314 /// </summary>
315 public override bool IsColliding
316 {
317 get { return (m_iscolliding || m_iscollidingGround); }
318 set
319 {
320 if (value)
321 {
322 m_colliderfilter += 3;
323 if (m_colliderfilter > 3)
324 m_colliderfilter = 3;
325 }
326 else
327 {
328 m_colliderfilter--;
329 if (m_colliderfilter < 0)
330 m_colliderfilter = 0;
331 }
332
333 if (m_colliderfilter == 0)
334 m_iscolliding = false;
335 else
336 {
337 m_pidControllerActive = true;
338 m_iscolliding = true;
339 m_freemove = false;
340 }
341 }
342 }
343
344 /// <summary>
345 /// Returns if an avatar is colliding with the ground
346 /// </summary>
347 public override bool CollidingGround
348 {
349 get { return m_iscollidingGround; }
350 set
351 {
352/* we now control this
353 if (value)
354 {
355 m_colliderGroundfilter += 2;
356 if (m_colliderGroundfilter > 2)
357 m_colliderGroundfilter = 2;
358 }
359 else
360 {
361 m_colliderGroundfilter--;
362 if (m_colliderGroundfilter < 0)
363 m_colliderGroundfilter = 0;
364 }
365
366 if (m_colliderGroundfilter == 0)
367 m_iscollidingGround = false;
368 else
369 m_iscollidingGround = true;
370 */
371 }
372
373 }
374
375 /// <summary>
376 /// Returns if the avatar is colliding with an object
377 /// </summary>
378 public override bool CollidingObj
379 {
380 get { return m_iscollidingObj; }
381 set
382 {
383 // Ubit filter this also
384 if (value)
385 {
386 m_colliderObjectfilter += 2;
387 if (m_colliderObjectfilter > 2)
388 m_colliderObjectfilter = 2;
389 }
390 else
391 {
392 m_colliderObjectfilter--;
393 if (m_colliderObjectfilter < 0)
394 m_colliderObjectfilter = 0;
395 }
396
397 if (m_colliderObjectfilter == 0)
398 m_iscollidingObj = false;
399 else
400 m_iscollidingObj = true;
401
402// m_iscollidingObj = value;
403
404 if (m_iscollidingObj)
405 m_pidControllerActive = false;
406 else
407 m_pidControllerActive = true;
408 }
409 }
410
411 /// <summary>
412 /// turn the PID controller on or off.
413 /// The PID Controller will turn on all by itself in many situations
414 /// </summary>
415 /// <param name="status"></param>
416 public void SetPidStatus(bool status)
417 {
418 m_pidControllerActive = status;
419 }
420
421 public override bool Stopped
422 {
423 get { return _zeroFlag; }
424 }
425
426 /// <summary>
427 /// This 'puts' an avatar somewhere in the physics space.
428 /// Not really a good choice unless you 'know' it's a good
429 /// spot otherwise you're likely to orbit the avatar.
430 /// </summary>
431 public override Vector3 Position
432 {
433 get { return _position; }
434 set
435 {
436 if (value.IsFinite())
437 {
438 if (value.Z > 9999999f)
439 {
440 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
441 }
442 if (value.Z < -100f)
443 {
444 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
445 }
446 AddChange(changes.Position, value);
447 }
448 else
449 {
450 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character");
451 }
452 }
453 }
454
455 public override Vector3 RotationalVelocity
456 {
457 get { return m_rotationalVelocity; }
458 set { m_rotationalVelocity = value; }
459 }
460
461 /// <summary>
462 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
463 /// and use it to offset landings properly
464 /// </summary>
465 public override Vector3 Size
466 {
467 get
468 {
469 return m_size;
470 }
471 set
472 {
473 if (value.IsFinite())
474 {
475 if(value.X <0.01f)
476 value.X = 0.01f;
477 if(value.Y <0.01f)
478 value.Y = 0.01f;
479 if(value.Z <0.01f)
480 value.Z = 0.01f;
481
482 AddChange(changes.Size, value);
483 }
484 else
485 {
486 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
487 }
488 }
489 }
490
491 public override void setAvatarSize(Vector3 size, float feetOffset)
492 {
493 if (size.IsFinite())
494 {
495 if (size.X < 0.01f)
496 size.X = 0.01f;
497 if (size.Y < 0.01f)
498 size.Y = 0.01f;
499 if (size.Z < 0.01f)
500 size.Z = 0.01f;
501
502 strAvatarSize st = new strAvatarSize();
503 st.size = size;
504 st.offset = feetOffset;
505 AddChange(changes.AvatarSize, st);
506 }
507 else
508 {
509 m_log.Warn("[PHYSICS]: Got a NaN AvatarSize from Scene on a Character");
510 }
511
512 }
513 /// <summary>
514 /// This creates the Avatar's physical Surrogate at the position supplied
515 /// </summary>
516 /// <param name="npositionX"></param>
517 /// <param name="npositionY"></param>
518 /// <param name="npositionZ"></param>
519
520 //
521 /// <summary>
522 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
523 /// This may be used in calculations in the scene/scenepresence
524 /// </summary>
525 public override float Mass
526 {
527 get
528 {
529 return m_mass;
530 }
531 }
532 public override void link(PhysicsActor obj)
533 {
534
535 }
536
537 public override void delink()
538 {
539
540 }
541
542 public override void LockAngularMotion(byte axislocks)
543 {
544
545 }
546
547
548 public override Vector3 Force
549 {
550 get { return _target_velocity; }
551 set { return; }
552 }
553
554 public override int VehicleType
555 {
556 get { return 0; }
557 set { return; }
558 }
559
560 public override void VehicleFloatParam(int param, float value)
561 {
562
563 }
564
565 public override void VehicleVectorParam(int param, Vector3 value)
566 {
567
568 }
569
570 public override void VehicleRotationParam(int param, Quaternion rotation)
571 {
572
573 }
574
575 public override void VehicleFlags(int param, bool remove)
576 {
577
578 }
579
580 public override void SetVolumeDetect(int param)
581 {
582
583 }
584
585 public override Vector3 CenterOfMass
586 {
587 get
588 {
589 Vector3 pos = _position;
590 return pos;
591 }
592 }
593
594 public override Vector3 GeometricCenter
595 {
596 get
597 {
598 Vector3 pos = _position;
599 return pos;
600 }
601 }
602
603 public override PrimitiveBaseShape Shape
604 {
605 set { return; }
606 }
607
608 public override Vector3 Velocity
609 {
610 get
611 {
612 return _velocity;
613 }
614 set
615 {
616 if (value.IsFinite())
617 {
618 AddChange(changes.Velocity, value);
619 }
620 else
621 {
622 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character");
623 }
624 }
625 }
626
627 public override Vector3 Torque
628 {
629 get { return Vector3.Zero; }
630 set { return; }
631 }
632
633 public override float CollisionScore
634 {
635 get { return 0f; }
636 set { }
637 }
638
639 public override bool Kinematic
640 {
641 get { return false; }
642 set { }
643 }
644
645 public override Quaternion Orientation
646 {
647 get { return m_orientation; }
648 set
649 {
650// fakeori = value;
651// givefakeori++;
652 value.Normalize();
653 AddChange(changes.Orientation, value);
654 }
655 }
656
657 public override Vector3 Acceleration
658 {
659 get { return _acceleration; }
660 set { }
661 }
662
663 public void SetAcceleration(Vector3 accel)
664 {
665 m_pidControllerActive = true;
666 _acceleration = accel;
667 }
668
669 /// <summary>
670 /// Adds the force supplied to the Target Velocity
671 /// The PID controller takes this target velocity and tries to make it a reality
672 /// </summary>
673 /// <param name="force"></param>
674 public override void AddForce(Vector3 force, bool pushforce)
675 {
676 if (force.IsFinite())
677 {
678 if (pushforce)
679 {
680 AddChange(changes.Force, force * m_density / (_parent_scene.ODE_STEPSIZE * 28f));
681 }
682 else
683 {
684 AddChange(changes.Velocity, force);
685 }
686 }
687 else
688 {
689 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character");
690 }
691 //m_lastUpdateSent = false;
692 }
693
694 public override void AddAngularForce(Vector3 force, bool pushforce)
695 {
696
697 }
698
699 public override void SetMomentum(Vector3 momentum)
700 {
701 if (momentum.IsFinite())
702 AddChange(changes.Momentum, momentum);
703 }
704
705
706 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
707 {
708 // sizes one day should came from visual parameters
709 float sx = m_size.X;
710 float sy = m_size.Y;
711 float sz = m_size.Z;
712
713 float bot = -sz * 0.5f + m_feetOffset;
714 boneOff = bot + 0.3f;
715
716 float feetsz = sz * 0.45f;
717 if (feetsz > 0.6f)
718 feetsz = 0.6f;
719
720 feetOff = bot + feetsz;
721
722 AvaAvaSizeXsq = 0.4f * sx;
723 AvaAvaSizeXsq *= AvaAvaSizeXsq;
724 AvaAvaSizeYsq = 0.5f * sy;
725 AvaAvaSizeYsq *= AvaAvaSizeYsq;
726
727 _parent_scene.waitForSpaceUnlock(_parent_scene.CharsSpace);
728
729 collider = d.HashSpaceCreate(_parent_scene.CharsSpace);
730 d.HashSpaceSetLevels(collider, -4, 3);
731 d.SpaceSetSublevel(collider, 3);
732 d.SpaceSetCleanup(collider, false);
733 d.GeomSetCategoryBits(collider, (uint)m_collisionCategories);
734 d.GeomSetCollideBits(collider, (uint)m_collisionFlags);
735
736 float r = m_size.X;
737 if (m_size.Y > r)
738 r = m_size.Y;
739 float l = m_size.Z - r;
740 r *= 0.5f;
741
742 capsule = d.CreateCapsule(collider, r, l);
743
744 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; // update mass
745
746 d.MassSetBoxTotal(out ShellMass, m_mass, m_size.X, m_size.Y, m_size.Z);
747
748 PID_D = basePID_D * m_mass / _parent_scene.ODE_STEPSIZE;
749 PID_P = basePID_P * m_mass / _parent_scene.ODE_STEPSIZE;
750
751 Body = d.BodyCreate(_parent_scene.world);
752
753 _zeroFlag = false;
754 m_pidControllerActive = true;
755 m_freemove = false;
756
757 _velocity = Vector3.Zero;
758
759 d.BodySetAutoDisableFlag(Body, false);
760 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
761
762 _position.X = npositionX;
763 _position.Y = npositionY;
764 _position.Z = npositionZ;
765
766 d.BodySetMass(Body, ref ShellMass);
767 d.GeomSetBody(capsule, Body);
768
769 // The purpose of the AMotor here is to keep the avatar's physical
770 // surrogate from rotating while moving
771 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
772 d.JointAttach(Amotor, Body, IntPtr.Zero);
773
774 d.JointSetAMotorMode(Amotor, 0);
775 d.JointSetAMotorNumAxes(Amotor, 3);
776 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
777 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
778 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
779
780 d.JointSetAMotorAngle(Amotor, 0, 0);
781 d.JointSetAMotorAngle(Amotor, 1, 0);
782 d.JointSetAMotorAngle(Amotor, 2, 0);
783
784 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM, 0f); // make it HARD
785 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM2, 0f);
786 d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM3, 0f);
787 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP, 0.8f);
788 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP2, 0.8f);
789 d.JointSetAMotorParam(Amotor, (int)dParam.StopERP3, 0.8f);
790
791 // These lowstops and high stops are effectively (no wiggle room)
792 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -1e-5f);
793 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 1e-5f);
794 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -1e-5f);
795 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 1e-5f);
796 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -1e-5f);
797 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 1e-5f);
798
799 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
800 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel2, 0);
801 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel3, 0);
802
803 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, 5e8f);
804 d.JointSetAMotorParam(Amotor, (int)dParam.FMax2, 5e8f);
805 d.JointSetAMotorParam(Amotor, (int)dParam.FMax3, 5e8f);
806 }
807
808 /// <summary>
809 /// Destroys the avatar body and geom
810
811 private void AvatarGeomAndBodyDestroy()
812 {
813 // Kill the Amotor
814 if (Amotor != IntPtr.Zero)
815 {
816 d.JointDestroy(Amotor);
817 Amotor = IntPtr.Zero;
818 }
819
820 if (Body != IntPtr.Zero)
821 {
822 //kill the body
823 d.BodyDestroy(Body);
824 Body = IntPtr.Zero;
825 }
826
827 //kill the Geoms
828 if (capsule != IntPtr.Zero)
829 {
830 _parent_scene.actor_name_map.Remove(capsule);
831 _parent_scene.waitForSpaceUnlock(collider);
832 d.GeomDestroy(capsule);
833 capsule = IntPtr.Zero;
834 }
835
836 if (collider != IntPtr.Zero)
837 {
838 d.SpaceDestroy(collider);
839 collider = IntPtr.Zero;
840 }
841
842 }
843
844 //in place 2D rotation around Z assuming rot is normalised and is a rotation around Z
845 public void RotateXYonZ(ref float x, ref float y, ref Quaternion rot)
846 {
847 float sin = 2.0f * rot.Z * rot.W;
848 float cos = rot.W * rot.W - rot.Z * rot.Z;
849 float tx = x;
850
851 x = tx * cos - y * sin;
852 y = tx * sin + y * cos;
853 }
854 public void RotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
855 {
856 float tx = x;
857 x = tx * cos - y * sin;
858 y = tx * sin + y * cos;
859 }
860 public void invRotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
861 {
862 float tx = x;
863 x = tx * cos + y * sin;
864 y = -tx * sin + y * cos;
865 }
866
867 public void invRotateXYonZ(ref float x, ref float y, ref Quaternion rot)
868 {
869 float sin = - 2.0f * rot.Z * rot.W;
870 float cos = rot.W * rot.W - rot.Z * rot.Z;
871 float tx = x;
872
873 x = tx * cos - y * sin;
874 y = tx * sin + y * cos;
875 }
876
877 public bool Collide(IntPtr me, IntPtr other, bool reverse, ref d.ContactGeom contact,
878 ref d.ContactGeom altContact , ref bool useAltcontact, ref bool feetcollision)
879 {
880 feetcollision = false;
881 useAltcontact = false;
882
883 if (me == capsule)
884 {
885 Vector3 offset;
886
887 float h = contact.pos.Z - _position.Z;
888 offset.Z = h - feetOff;
889
890 offset.X = contact.pos.X - _position.X;
891 offset.Y = contact.pos.Y - _position.Y;
892
893 d.GeomClassID gtype = d.GeomGetClass(other);
894 if (gtype == d.GeomClassID.CapsuleClass)
895 {
896 Vector3 roff = offset * Quaternion.Inverse(m_orientation2D);
897 float r = roff.X *roff.X / AvaAvaSizeXsq;
898 r += (roff.Y * roff.Y) / AvaAvaSizeYsq;
899 if (r > 1.0f)
900 return false;
901
902 float dp = 1.0f -(float)Math.Sqrt((double)r);
903 if (dp > 0.05f)
904 dp = 0.05f;
905
906 contact.depth = dp;
907
908 if (offset.Z < 0)
909 {
910 feetcollision = true;
911 if (h < boneOff)
912 {
913 m_collideNormal.X = contact.normal.X;
914 m_collideNormal.Y = contact.normal.Y;
915 m_collideNormal.Z = contact.normal.Z;
916 IsColliding = true;
917 }
918 }
919 return true;
920 }
921/*
922 d.AABB aabb;
923 d.GeomGetAABB(other,out aabb);
924 float othertop = aabb.MaxZ - _position.Z;
925*/
926// if (offset.Z > 0 || othertop > -feetOff || contact.normal.Z > 0.35f)
927 if (offset.Z > 0 || contact.normal.Z > 0.35f)
928 {
929 if (offset.Z <= 0)
930 {
931 feetcollision = true;
932 if (h < boneOff)
933 {
934 m_collideNormal.X = contact.normal.X;
935 m_collideNormal.Y = contact.normal.Y;
936 m_collideNormal.Z = contact.normal.Z;
937 IsColliding = true;
938 }
939 }
940 return true;
941 }
942
943 altContact = contact;
944 useAltcontact = true;
945
946 offset.Z -= 0.2f;
947
948 offset.Normalize();
949
950 if (contact.depth > 0.1f)
951 contact.depth = 0.1f;
952
953 if (reverse)
954 {
955 altContact.normal.X = offset.X;
956 altContact.normal.Y = offset.Y;
957 altContact.normal.Z = offset.Z;
958 }
959 else
960 {
961 altContact.normal.X = -offset.X;
962 altContact.normal.Y = -offset.Y;
963 altContact.normal.Z = -offset.Z;
964 }
965
966 feetcollision = true;
967 if (h < boneOff)
968 {
969 m_collideNormal.X = contact.normal.X;
970 m_collideNormal.Y = contact.normal.Y;
971 m_collideNormal.Z = contact.normal.Z;
972 IsColliding = true;
973 }
974 return true;
975 }
976 return false;
977 }
978
979 /// <summary>
980 /// Called from Simulate
981 /// This is the avatar's movement control + PID Controller
982 /// </summary>
983 /// <param name="timeStep"></param>
984 public void Move(List<OdeCharacter> defects)
985 {
986 if (Body == IntPtr.Zero)
987 return;
988
989 d.Vector3 dtmp = d.BodyGetPosition(Body);
990 Vector3 localpos = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
991
992 // the Amotor still lets avatar rotation to drift during colisions
993 // so force it back to identity
994
995 d.Quaternion qtmp;
996 qtmp.W = m_orientation2D.W;
997 qtmp.X = m_orientation2D.X;
998 qtmp.Y = m_orientation2D.Y;
999 qtmp.Z = m_orientation2D.Z;
1000 d.BodySetQuaternion(Body, ref qtmp);
1001
1002 if (m_pidControllerActive == false)
1003 {
1004 _zeroPosition = localpos;
1005 }
1006
1007 if (!localpos.IsFinite())
1008 {
1009 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1010 defects.Add(this);
1011 // _parent_scene.RemoveCharacter(this);
1012
1013 // destroy avatar capsule and related ODE data
1014 AvatarGeomAndBodyDestroy();
1015 return;
1016 }
1017
1018 // check outbounds forcing to be in world
1019 bool fixbody = false;
1020 if (localpos.X < 0.0f)
1021 {
1022 fixbody = true;
1023 localpos.X = 0.1f;
1024 }
1025 else if (localpos.X > _parent_scene.WorldExtents.X - 0.1f)
1026 {
1027 fixbody = true;
1028 localpos.X = _parent_scene.WorldExtents.X - 0.1f;
1029 }
1030 if (localpos.Y < 0.0f)
1031 {
1032 fixbody = true;
1033 localpos.Y = 0.1f;
1034 }
1035 else if (localpos.Y > _parent_scene.WorldExtents.Y - 0.1)
1036 {
1037 fixbody = true;
1038 localpos.Y = _parent_scene.WorldExtents.Y - 0.1f;
1039 }
1040 if (fixbody)
1041 {
1042 m_freemove = false;
1043 d.BodySetPosition(Body, localpos.X, localpos.Y, localpos.Z);
1044 }
1045
1046 float breakfactor;
1047
1048 Vector3 vec = Vector3.Zero;
1049 dtmp = d.BodyGetLinearVel(Body);
1050 Vector3 vel = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
1051 float velLengthSquared = vel.LengthSquared();
1052
1053 Vector3 ctz = _target_velocity;
1054
1055 float movementdivisor = 1f;
1056 //Ubit change divisions into multiplications below
1057 if (!m_alwaysRun)
1058 movementdivisor = 1 / walkDivisor;
1059 else
1060 movementdivisor = 1 / runDivisor;
1061
1062 ctz.X *= movementdivisor;
1063 ctz.Y *= movementdivisor;
1064
1065 //******************************************
1066 // colide with land
1067
1068 d.AABB aabb;
1069// d.GeomGetAABB(feetbox, out aabb);
1070 d.GeomGetAABB(capsule, out aabb);
1071 float chrminZ = aabb.MinZ; // move up a bit
1072 Vector3 posch = localpos;
1073
1074 float ftmp;
1075
1076 if (flying)
1077 {
1078 ftmp = timeStep;
1079 posch.X += vel.X * ftmp;
1080 posch.Y += vel.Y * ftmp;
1081 }
1082
1083 float terrainheight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);
1084 if (chrminZ < terrainheight)
1085 {
1086 if (ctz.Z < 0)
1087 ctz.Z = 0;
1088
1089 Vector3 n = _parent_scene.GetTerrainNormalAtXY(posch.X, posch.Y);
1090 float depth = terrainheight - chrminZ;
1091
1092 vec.Z = depth * PID_P * 50;
1093
1094 if (!flying)
1095 vec.Z += -vel.Z * PID_D;
1096
1097 if (depth < 0.2f)
1098 {
1099 m_colliderGroundfilter++;
1100 if (m_colliderGroundfilter > 2)
1101 {
1102 m_iscolliding = true;
1103 m_colliderfilter = 2;
1104
1105 if (m_colliderGroundfilter > 10)
1106 {
1107 m_colliderGroundfilter = 10;
1108 m_freemove = false;
1109 }
1110
1111 m_collideNormal.X = n.X;
1112 m_collideNormal.Y = n.Y;
1113 m_collideNormal.Z = n.Z;
1114
1115 m_iscollidingGround = true;
1116
1117
1118 ContactPoint contact = new ContactPoint();
1119 contact.PenetrationDepth = depth;
1120 contact.Position.X = localpos.X;
1121 contact.Position.Y = localpos.Y;
1122 contact.Position.Z = terrainheight;
1123 contact.SurfaceNormal.X = -n.X;
1124 contact.SurfaceNormal.Y = -n.Y;
1125 contact.SurfaceNormal.Z = -n.Z;
1126 contact.RelativeSpeed = -vel.Z;
1127 contact.CharacterFeet = true;
1128 AddCollisionEvent(0, contact);
1129
1130// vec.Z *= 0.5f;
1131 }
1132 }
1133
1134 else
1135 {
1136 m_colliderGroundfilter -= 5;
1137 if (m_colliderGroundfilter <= 0)
1138 {
1139 m_colliderGroundfilter = 0;
1140 m_iscollidingGround = false;
1141 }
1142 }
1143 }
1144 else
1145 {
1146 m_colliderGroundfilter -= 5;
1147 if (m_colliderGroundfilter <= 0)
1148 {
1149 m_colliderGroundfilter = 0;
1150 m_iscollidingGround = false;
1151 }
1152 }
1153
1154 bool hoverPIDActive = false;
1155
1156 if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
1157 {
1158 hoverPIDActive = true;
1159
1160 switch (m_PIDHoverType)
1161 {
1162 case PIDHoverType.Ground:
1163 m_targetHoverHeight = terrainheight + m_PIDHoverHeight;
1164 break;
1165
1166 case PIDHoverType.GroundAndWater:
1167 float waterHeight = _parent_scene.GetWaterLevel();
1168 if (terrainheight > waterHeight)
1169 m_targetHoverHeight = terrainheight + m_PIDHoverHeight;
1170 else
1171 m_targetHoverHeight = waterHeight + m_PIDHoverHeight;
1172 break;
1173 } // end switch (m_PIDHoverType)
1174
1175 // don't go underground
1176 if (m_targetHoverHeight > terrainheight + 0.5f * (aabb.MaxZ - aabb.MinZ))
1177 {
1178 float fz = (m_targetHoverHeight - localpos.Z);
1179
1180 // if error is zero, use position control; otherwise, velocity control
1181 if (Math.Abs(fz) < 0.01f)
1182 {
1183 ctz.Z = 0;
1184 }
1185 else
1186 {
1187 _zeroFlag = false;
1188 fz /= m_PIDHoverTau;
1189
1190 float tmp = Math.Abs(fz);
1191 if (tmp > 50)
1192 fz = 50 * Math.Sign(fz);
1193 else if (tmp < 0.1)
1194 fz = 0.1f * Math.Sign(fz);
1195
1196 ctz.Z = fz;
1197 }
1198 }
1199 }
1200
1201 //******************************************
1202 if (!m_iscolliding)
1203 m_collideNormal.Z = 0;
1204
1205 bool tviszero = (ctz.X == 0.0f && ctz.Y == 0.0f && ctz.Z == 0.0f);
1206
1207 if (!tviszero)
1208 {
1209 m_freemove = false;
1210
1211 // movement relative to surface if moving on it
1212 // dont disturbe vertical movement, ie jumps
1213 if (m_iscolliding && !flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f)
1214 {
1215 float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y;
1216 ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X);
1217 ctz.Y *= (float)Math.Sqrt(1 - m_collideNormal.Y * m_collideNormal.Y);
1218 ctz.Z -= p;
1219 if (ctz.Z < 0)
1220 ctz.Z *= 2;
1221
1222 }
1223
1224 }
1225
1226 if (!m_freemove)
1227 {
1228
1229 // if velocity is zero, use position control; otherwise, velocity control
1230 if (tviszero && m_iscolliding && !flying)
1231 {
1232 // keep track of where we stopped. No more slippin' & slidin'
1233 if (!_zeroFlag)
1234 {
1235 _zeroFlag = true;
1236 _zeroPosition = localpos;
1237 }
1238 if (m_pidControllerActive)
1239 {
1240 // We only want to deactivate the PID Controller if we think we want to have our surrogate
1241 // react to the physics scene by moving it's position.
1242 // Avatar to Avatar collisions
1243 // Prim to avatar collisions
1244
1245 vec.X = -vel.X * PID_D * 2f + (_zeroPosition.X - localpos.X) * (PID_P * 5);
1246 vec.Y = -vel.Y * PID_D * 2f + (_zeroPosition.Y - localpos.Y) * (PID_P * 5);
1247 if(vel.Z > 0)
1248 vec.Z += -vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P;
1249 else
1250 vec.Z += (-vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P) * 0.2f;
1251/*
1252 if (flying)
1253 {
1254 vec.Z += -vel.Z * PID_D + (_zeroPosition.Z - localpos.Z) * PID_P;
1255 }
1256*/
1257 }
1258 //PidStatus = true;
1259 }
1260 else
1261 {
1262 m_pidControllerActive = true;
1263 _zeroFlag = false;
1264
1265 if (m_iscolliding)
1266 {
1267 if (!flying)
1268 {
1269 // we are on a surface
1270 if (ctz.Z > 0f)
1271 {
1272 // moving up or JUMPING
1273 vec.Z += (ctz.Z - vel.Z) * PID_D * 2f;
1274 vec.X += (ctz.X - vel.X) * (PID_D);
1275 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1276 }
1277 else
1278 {
1279 // we are moving down on a surface
1280 if (ctz.Z == 0)
1281 {
1282 if (vel.Z > 0)
1283 vec.Z -= vel.Z * PID_D * 2f;
1284 vec.X += (ctz.X - vel.X) * (PID_D);
1285 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1286 }
1287 // intencionally going down
1288 else
1289 {
1290 if (ctz.Z < vel.Z)
1291 vec.Z += (ctz.Z - vel.Z) * PID_D;
1292 else
1293 {
1294 }
1295
1296 if (Math.Abs(ctz.X) > Math.Abs(vel.X))
1297 vec.X += (ctz.X - vel.X) * (PID_D);
1298 if (Math.Abs(ctz.Y) > Math.Abs(vel.Y))
1299 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1300 }
1301 }
1302
1303 // We're standing on something
1304 }
1305 else
1306 {
1307 // We're flying and colliding with something
1308 vec.X += (ctz.X - vel.X) * (PID_D * 0.0625f);
1309 vec.Y += (ctz.Y - vel.Y) * (PID_D * 0.0625f);
1310 vec.Z += (ctz.Z - vel.Z) * (PID_D * 0.0625f);
1311 }
1312 }
1313 else // ie not colliding
1314 {
1315 if (flying || hoverPIDActive) //(!m_iscolliding && flying)
1316 {
1317 // we're in mid air suspended
1318 vec.X += (ctz.X - vel.X) * (PID_D);
1319 vec.Y += (ctz.Y - vel.Y) * (PID_D);
1320 vec.Z += (ctz.Z - vel.Z) * (PID_D);
1321 }
1322
1323 else
1324 {
1325 // we're not colliding and we're not flying so that means we're falling!
1326 // m_iscolliding includes collisions with the ground.
1327
1328 // d.Vector3 pos = d.BodyGetPosition(Body);
1329 vec.X += (ctz.X - vel.X) * PID_D * 0.833f;
1330 vec.Y += (ctz.Y - vel.Y) * PID_D * 0.833f;
1331 // hack for breaking on fall
1332 if (ctz.Z == -9999f)
1333 vec.Z += -vel.Z * PID_D - _parent_scene.gravityz * m_mass;
1334 }
1335 }
1336 }
1337
1338 if (velLengthSquared > 2500.0f) // 50m/s apply breaks
1339 {
1340 breakfactor = 0.16f * m_mass;
1341 vec.X -= breakfactor * vel.X;
1342 vec.Y -= breakfactor * vel.Y;
1343 vec.Z -= breakfactor * vel.Z;
1344 }
1345 }
1346 else
1347 {
1348 breakfactor = m_mass;
1349 vec.X -= breakfactor * vel.X;
1350 vec.Y -= breakfactor * vel.Y;
1351 if (flying)
1352 vec.Z -= 0.5f * breakfactor * vel.Z;
1353 else
1354 vec.Z -= .16f* m_mass * vel.Z;
1355 }
1356
1357 if (flying || hoverPIDActive)
1358 {
1359 vec.Z -= _parent_scene.gravityz * m_mass;
1360
1361 if(!hoverPIDActive)
1362 {
1363 //Added for auto fly height. Kitto Flora
1364 float target_altitude = terrainheight + MinimumGroundFlightOffset;
1365
1366 if (localpos.Z < target_altitude)
1367 {
1368 vec.Z += (target_altitude - localpos.Z) * PID_P * 5.0f;
1369 }
1370 // end add Kitto Flora
1371 }
1372 }
1373
1374 if (vec.IsFinite())
1375 {
1376 if (vec.X != 0 || vec.Y !=0 || vec.Z !=0)
1377 d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
1378 }
1379 else
1380 {
1381 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()");
1382 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
1383 defects.Add(this);
1384 // _parent_scene.RemoveCharacter(this);
1385 // destroy avatar capsule and related ODE data
1386 AvatarGeomAndBodyDestroy();
1387 return;
1388 }
1389
1390 // update our local ideia of position velocity and aceleration
1391 // _position = localpos;
1392 _position = localpos;
1393
1394 if (_zeroFlag)
1395 {
1396 _velocity = Vector3.Zero;
1397 _acceleration = Vector3.Zero;
1398 m_rotationalVelocity = Vector3.Zero;
1399 }
1400 else
1401 {
1402 Vector3 a =_velocity; // previus velocity
1403 SetSmooth(ref _velocity, ref vel, 2);
1404 a = (_velocity - a) * invtimeStep;
1405 SetSmooth(ref _acceleration, ref a, 2);
1406
1407 dtmp = d.BodyGetAngularVel(Body);
1408 m_rotationalVelocity.X = 0f;
1409 m_rotationalVelocity.Y = 0f;
1410 m_rotationalVelocity.Z = dtmp.Z;
1411 Math.Round(m_rotationalVelocity.Z,3);
1412 }
1413 }
1414
1415 public void round(ref Vector3 v, int digits)
1416 {
1417 v.X = (float)Math.Round(v.X, digits);
1418 v.Y = (float)Math.Round(v.Y, digits);
1419 v.Z = (float)Math.Round(v.Z, digits);
1420 }
1421
1422 public void SetSmooth(ref Vector3 dst, ref Vector3 value)
1423 {
1424 dst.X = 0.1f * dst.X + 0.9f * value.X;
1425 dst.Y = 0.1f * dst.Y + 0.9f * value.Y;
1426 dst.Z = 0.1f * dst.Z + 0.9f * value.Z;
1427 }
1428
1429 public void SetSmooth(ref Vector3 dst, ref Vector3 value, int rounddigits)
1430 {
1431 dst.X = 0.4f * dst.X + 0.6f * value.X;
1432 dst.X = (float)Math.Round(dst.X, rounddigits);
1433
1434 dst.Y = 0.4f * dst.Y + 0.6f * value.Y;
1435 dst.Y = (float)Math.Round(dst.Y, rounddigits);
1436
1437 dst.Z = 0.4f * dst.Z + 0.6f * value.Z;
1438 dst.Z = (float)Math.Round(dst.Z, rounddigits);
1439 }
1440
1441
1442 /// <summary>
1443 /// Updates the reported position and velocity.
1444 /// Used to copy variables from unmanaged space at heartbeat rate and also trigger scene updates acording
1445 /// also outbounds checking
1446 /// copy and outbounds now done in move(..) at ode rate
1447 ///
1448 /// </summary>
1449 public void UpdatePositionAndVelocity()
1450 {
1451 return;
1452
1453// if (Body == IntPtr.Zero)
1454// return;
1455
1456 }
1457
1458 /// <summary>
1459 /// Cleanup the things we use in the scene.
1460 /// </summary>
1461 public void Destroy()
1462 {
1463 AddChange(changes.Remove, null);
1464 }
1465
1466 public override void CrossingFailure()
1467 {
1468 }
1469
1470 public override Vector3 PIDTarget { set { return; } }
1471 public override bool PIDActive {get {return m_pidControllerActive;} set { return; } }
1472 public override float PIDTau { set { return; } }
1473
1474 public override float PIDHoverHeight
1475 {
1476 set
1477 {
1478 AddChange(changes.PIDHoverHeight,value);
1479 }
1480 }
1481 public override bool PIDHoverActive
1482 {
1483 get
1484 {
1485 return m_useHoverPID;
1486 }
1487 set
1488 {
1489 AddChange(changes.PIDHoverActive, value);
1490 }
1491 }
1492
1493 public override PIDHoverType PIDHoverType
1494 {
1495 set
1496 {
1497 AddChange(changes.PIDHoverType,value);
1498 }
1499 }
1500
1501 public override float PIDHoverTau
1502 {
1503 set
1504 {
1505 float tmp =0;
1506 if (value > 0)
1507 {
1508 float mint = (0.05f > timeStep ? 0.05f : timeStep);
1509 if (value < mint)
1510 tmp = mint;
1511 else
1512 tmp = value;
1513 }
1514 AddChange(changes.PIDHoverTau, tmp);
1515 }
1516 }
1517
1518 public override Quaternion APIDTarget { set { return; } }
1519
1520 public override bool APIDActive { set { return; } }
1521
1522 public override float APIDStrength { set { return; } }
1523
1524 public override float APIDDamping { set { return; } }
1525
1526
1527 public override void SubscribeEvents(int ms)
1528 {
1529 m_eventsubscription = ms;
1530 m_cureventsubscription = 0;
1531 if (CollisionEventsThisFrame == null)
1532 CollisionEventsThisFrame = new CollisionEventUpdate();
1533 SentEmptyCollisionsEvent = false;
1534 }
1535
1536 public override void UnSubscribeEvents()
1537 {
1538 if (CollisionEventsThisFrame != null)
1539 {
1540 lock (CollisionEventsThisFrame)
1541 {
1542 CollisionEventsThisFrame.Clear();
1543 CollisionEventsThisFrame = null;
1544 }
1545 }
1546 m_eventsubscription = 0;
1547 }
1548
1549 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1550 {
1551 if (CollisionEventsThisFrame == null)
1552 CollisionEventsThisFrame = new CollisionEventUpdate();
1553 lock (CollisionEventsThisFrame)
1554 {
1555 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1556 _parent_scene.AddCollisionEventReporting(this);
1557 }
1558 }
1559
1560 public void SendCollisions()
1561 {
1562 if (CollisionEventsThisFrame == null)
1563 return;
1564
1565 lock (CollisionEventsThisFrame)
1566 {
1567 if (m_cureventsubscription < m_eventsubscription)
1568 return;
1569
1570 m_cureventsubscription = 0;
1571
1572 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1573
1574 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1575 {
1576 base.SendCollisionUpdate(CollisionEventsThisFrame);
1577
1578 if (ncolisions == 0)
1579 {
1580 SentEmptyCollisionsEvent = true;
1581 _parent_scene.RemoveCollisionEventReporting(this);
1582 }
1583 else
1584 {
1585 SentEmptyCollisionsEvent = false;
1586 CollisionEventsThisFrame.Clear();
1587 }
1588 }
1589 }
1590 }
1591
1592 internal void AddCollisionFrameTime(int t)
1593 {
1594 // protect it from overflow crashing
1595 if (m_cureventsubscription < 50000)
1596 m_cureventsubscription += t;
1597 }
1598
1599 public override bool SubscribedEvents()
1600 {
1601 if (m_eventsubscription > 0)
1602 return true;
1603 return false;
1604 }
1605
1606 private void changePhysicsStatus(bool NewStatus)
1607 {
1608 if (NewStatus != m_isPhysical)
1609 {
1610 if (NewStatus)
1611 {
1612 AvatarGeomAndBodyDestroy();
1613
1614 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z);
1615
1616 _parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1617 _parent_scene.actor_name_map[capsule] = (PhysicsActor)this;
1618 _parent_scene.AddCharacter(this);
1619 }
1620 else
1621 {
1622 _parent_scene.RemoveCollisionEventReporting(this);
1623 _parent_scene.RemoveCharacter(this);
1624 // destroy avatar capsule and related ODE data
1625 AvatarGeomAndBodyDestroy();
1626 }
1627 m_freemove = false;
1628 m_isPhysical = NewStatus;
1629 }
1630 }
1631
1632 private void changeAdd()
1633 {
1634 changePhysicsStatus(true);
1635 }
1636
1637 private void changeRemove()
1638 {
1639 changePhysicsStatus(false);
1640 }
1641
1642 private void changeShape(PrimitiveBaseShape arg)
1643 {
1644 }
1645
1646 private void changeAvatarSize(strAvatarSize st)
1647 {
1648 m_feetOffset = st.offset;
1649 changeSize(st.size);
1650 }
1651
1652 private void changeSize(Vector3 pSize)
1653 {
1654 if (pSize.IsFinite())
1655 {
1656 // for now only look to Z changes since viewers also don't change X and Y
1657 if (pSize.Z != m_size.Z)
1658 {
1659 AvatarGeomAndBodyDestroy();
1660
1661
1662 float oldsz = m_size.Z;
1663 m_size = pSize;
1664
1665
1666 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1667 _position.Z + (m_size.Z - oldsz) * 0.5f);
1668
1669 Velocity = Vector3.Zero;
1670
1671
1672 _parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1673 _parent_scene.actor_name_map[capsule] = (PhysicsActor)this;
1674 }
1675 m_freemove = false;
1676 m_pidControllerActive = true;
1677 }
1678 else
1679 {
1680 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character");
1681 }
1682 }
1683
1684 private void changePosition( Vector3 newPos)
1685 {
1686 if (Body != IntPtr.Zero)
1687 d.BodySetPosition(Body, newPos.X, newPos.Y, newPos.Z);
1688 _position = newPos;
1689 m_freemove = false;
1690 m_pidControllerActive = true;
1691 }
1692
1693 private void changeOrientation(Quaternion newOri)
1694 {
1695 if (m_orientation != newOri)
1696 {
1697 m_orientation = newOri; // keep a copy for core use
1698 // but only use rotations around Z
1699
1700 m_orientation2D.W = newOri.W;
1701 m_orientation2D.Z = newOri.Z;
1702
1703 float t = m_orientation2D.W * m_orientation2D.W + m_orientation2D.Z * m_orientation2D.Z;
1704 if (t > 0)
1705 {
1706 t = 1.0f / (float)Math.Sqrt(t);
1707 m_orientation2D.W *= t;
1708 m_orientation2D.Z *= t;
1709 }
1710 else
1711 {
1712 m_orientation2D.W = 1.0f;
1713 m_orientation2D.Z = 0f;
1714 }
1715 m_orientation2D.Y = 0f;
1716 m_orientation2D.X = 0f;
1717
1718 d.Quaternion myrot = new d.Quaternion();
1719 myrot.X = m_orientation2D.X;
1720 myrot.Y = m_orientation2D.Y;
1721 myrot.Z = m_orientation2D.Z;
1722 myrot.W = m_orientation2D.W;
1723 d.BodySetQuaternion(Body, ref myrot);
1724 }
1725 }
1726
1727 private void changeVelocity(Vector3 newVel)
1728 {
1729 m_pidControllerActive = true;
1730 m_freemove = false;
1731 _target_velocity = newVel;
1732 }
1733
1734 private void changeSetTorque(Vector3 newTorque)
1735 {
1736 }
1737
1738 private void changeAddForce(Vector3 newForce)
1739 {
1740 }
1741
1742 private void changeAddAngularForce(Vector3 arg)
1743 {
1744 }
1745
1746 private void changeAngularLock(byte arg)
1747 {
1748 }
1749
1750 private void changeFloatOnWater(bool arg)
1751 {
1752 }
1753
1754 private void changeVolumedetetion(bool arg)
1755 {
1756 }
1757
1758 private void changeSelectedStatus(bool arg)
1759 {
1760 }
1761
1762 private void changeDisable(bool arg)
1763 {
1764 }
1765
1766 private void changeBuilding(bool arg)
1767 {
1768 }
1769
1770 private void setFreeMove()
1771 {
1772 m_pidControllerActive = true;
1773 _zeroFlag = false;
1774 _target_velocity = Vector3.Zero;
1775 m_freemove = true;
1776 m_colliderfilter = -1;
1777 m_colliderObjectfilter = -1;
1778 m_colliderGroundfilter = -1;
1779
1780 m_iscolliding = false;
1781 m_iscollidingGround = false;
1782 m_iscollidingObj = false;
1783
1784 CollisionEventsThisFrame.Clear();
1785 }
1786
1787 private void changeForce(Vector3 newForce)
1788 {
1789 setFreeMove();
1790
1791 if (Body != IntPtr.Zero)
1792 {
1793 if (newForce.X != 0f || newForce.Y != 0f || newForce.Z != 0)
1794 d.BodyAddForce(Body, newForce.X, newForce.Y, newForce.Z);
1795 }
1796 }
1797
1798 // for now momentum is actually velocity
1799 private void changeMomentum(Vector3 newmomentum)
1800 {
1801 _velocity = newmomentum;
1802 setFreeMove();
1803
1804 if (Body != IntPtr.Zero)
1805 d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z);
1806 }
1807
1808 private void changePIDHoverHeight(float val)
1809 {
1810 m_PIDHoverHeight = val;
1811 if (val == 0)
1812 m_useHoverPID = false;
1813 }
1814
1815 private void changePIDHoverType(PIDHoverType type)
1816 {
1817 m_PIDHoverType = type;
1818 }
1819
1820 private void changePIDHoverTau(float tau)
1821 {
1822 m_PIDHoverTau = tau;
1823 }
1824
1825 private void changePIDHoverActive(bool active)
1826 {
1827 m_useHoverPID = active;
1828 }
1829
1830 private void donullchange()
1831 {
1832 }
1833
1834 public bool DoAChange(changes what, object arg)
1835 {
1836 if (collider == IntPtr.Zero && what != changes.Add && what != changes.Remove)
1837 {
1838 return false;
1839 }
1840
1841 // nasty switch
1842 switch (what)
1843 {
1844 case changes.Add:
1845 changeAdd();
1846 break;
1847 case changes.Remove:
1848 changeRemove();
1849 break;
1850
1851 case changes.Position:
1852 changePosition((Vector3)arg);
1853 break;
1854
1855 case changes.Orientation:
1856 changeOrientation((Quaternion)arg);
1857 break;
1858
1859 case changes.PosOffset:
1860 donullchange();
1861 break;
1862
1863 case changes.OriOffset:
1864 donullchange();
1865 break;
1866
1867 case changes.Velocity:
1868 changeVelocity((Vector3)arg);
1869 break;
1870
1871 // case changes.Acceleration:
1872 // changeacceleration((Vector3)arg);
1873 // break;
1874 // case changes.AngVelocity:
1875 // changeangvelocity((Vector3)arg);
1876 // break;
1877
1878 case changes.Force:
1879 changeForce((Vector3)arg);
1880 break;
1881
1882 case changes.Torque:
1883 changeSetTorque((Vector3)arg);
1884 break;
1885
1886 case changes.AddForce:
1887 changeAddForce((Vector3)arg);
1888 break;
1889
1890 case changes.AddAngForce:
1891 changeAddAngularForce((Vector3)arg);
1892 break;
1893
1894 case changes.AngLock:
1895 changeAngularLock((byte)arg);
1896 break;
1897
1898 case changes.Size:
1899 changeSize((Vector3)arg);
1900 break;
1901
1902 case changes.AvatarSize:
1903 changeAvatarSize((strAvatarSize)arg);
1904 break;
1905
1906 case changes.Momentum:
1907 changeMomentum((Vector3)arg);
1908 break;
1909
1910 case changes.PIDHoverHeight:
1911 changePIDHoverHeight((float)arg);
1912 break;
1913
1914 case changes.PIDHoverType:
1915 changePIDHoverType((PIDHoverType)arg);
1916 break;
1917
1918 case changes.PIDHoverTau:
1919 changePIDHoverTau((float)arg);
1920 break;
1921
1922 case changes.PIDHoverActive:
1923 changePIDHoverActive((bool)arg);
1924 break;
1925
1926/* not in use for now
1927 case changes.Shape:
1928 changeShape((PrimitiveBaseShape)arg);
1929 break;
1930
1931 case changes.CollidesWater:
1932 changeFloatOnWater((bool)arg);
1933 break;
1934
1935 case changes.VolumeDtc:
1936 changeVolumedetetion((bool)arg);
1937 break;
1938
1939 case changes.Physical:
1940 changePhysicsStatus((bool)arg);
1941 break;
1942
1943 case changes.Selected:
1944 changeSelectedStatus((bool)arg);
1945 break;
1946
1947 case changes.disabled:
1948 changeDisable((bool)arg);
1949 break;
1950
1951 case changes.building:
1952 changeBuilding((bool)arg);
1953 break;
1954*/
1955 case changes.Null:
1956 donullchange();
1957 break;
1958
1959 default:
1960 donullchange();
1961 break;
1962 }
1963 return false;
1964 }
1965
1966 public void AddChange(changes what, object arg)
1967 {
1968 _parent_scene.AddChange((PhysicsActor)this, what, arg);
1969 }
1970
1971 private struct strAvatarSize
1972 {
1973 public Vector3 size;
1974 public float offset;
1975 }
1976
1977 }
1978}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs
new file mode 100644
index 0000000..c3b4dd8
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs
@@ -0,0 +1,1096 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces
29 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
30 * ODEPrim.cs contains methods dealing with Prim editing, Prim
31 * characteristics and Kinetic motion.
32 * ODEDynamics.cs contains methods dealing with Prim Physical motion
33 * (dynamics) and the associated settings. Old Linear and angular
34 * motors for dynamic motion have been replace with MoveLinear()
35 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
36 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
37 * switch between 'VEHICLE' parameter use and general dynamics
38 * settings use.
39 */
40
41// Extensive change Ubit 2012
42
43using System;
44using System.Collections.Generic;
45using System.Reflection;
46using System.Runtime.InteropServices;
47using log4net;
48using OpenMetaverse;
49using OdeAPI;
50using OpenSim.Framework;
51using OpenSim.Region.PhysicsModules.SharedBase;
52
53namespace OpenSim.Region.PhysicsModule.ubOde
54{
55 public class ODEDynamics
56 {
57 public Vehicle Type
58 {
59 get { return m_type; }
60 }
61
62 private OdePrim rootPrim;
63 private ODEScene _pParentScene;
64
65 // Vehicle properties
66 // WARNING this are working copies for internel use
67 // their values may not be the corresponding parameter
68
69 private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
70 private Quaternion m_RollreferenceFrame = Quaternion.Identity; // what hell is this ?
71
72 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
73
74 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
75 // HOVER_TERRAIN_ONLY
76 // HOVER_GLOBAL_HEIGHT
77 // NO_DEFLECTION_UP
78 // HOVER_WATER_ONLY
79 // HOVER_UP_ONLY
80 // LIMIT_MOTOR_UP
81 // LIMIT_ROLL_ONLY
82 private Vector3 m_BlockingEndPoint = Vector3.Zero; // not sl
83
84 // Linear properties
85 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
86 private Vector3 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
87 private float m_linearMotorDecayTimescale = 120;
88 private float m_linearMotorTimescale = 1000;
89 private Vector3 m_linearMotorOffset = Vector3.Zero;
90
91 //Angular properties
92 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
93 private float m_angularMotorTimescale = 1000; // motor angular velocity ramp up rate
94 private float m_angularMotorDecayTimescale = 120; // motor angular velocity decay rate
95 private Vector3 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); // body angular velocity decay rate
96
97 //Deflection properties
98 private float m_angularDeflectionEfficiency = 0;
99 private float m_angularDeflectionTimescale = 1000;
100 private float m_linearDeflectionEfficiency = 0;
101 private float m_linearDeflectionTimescale = 1000;
102
103 //Banking properties
104 private float m_bankingEfficiency = 0;
105 private float m_bankingMix = 0;
106 private float m_bankingTimescale = 1000;
107
108 //Hover and Buoyancy properties
109 private float m_VhoverHeight = 0f;
110 private float m_VhoverEfficiency = 0f;
111 private float m_VhoverTimescale = 1000f;
112 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
113 // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity)
114 // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity.
115 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
116
117 //Attractor properties
118 private float m_verticalAttractionEfficiency = 1.0f; // damped
119 private float m_verticalAttractionTimescale = 1000f; // Timescale > 300 means no vert attractor.
120
121
122 // auxiliar
123 private float m_lmEfect = 0f; // current linear motor eficiency
124 private float m_lmDecay = 0f; // current linear decay
125
126 private float m_amEfect = 0; // current angular motor eficiency
127 private float m_amDecay = 0f; // current linear decay
128
129 private float m_ffactor = 1.0f;
130
131 private float m_timestep = 0.02f;
132 private float m_invtimestep = 50;
133
134
135 float m_ampwr;
136 float m_amdampX;
137 float m_amdampY;
138 float m_amdampZ;
139
140 float m_gravmod;
141
142 public float FrictionFactor
143 {
144 get
145 {
146 return m_ffactor;
147 }
148 }
149
150 public float GravMod
151 {
152 set
153 {
154 m_gravmod = value;
155 }
156 }
157
158
159 public ODEDynamics(OdePrim rootp)
160 {
161 rootPrim = rootp;
162 _pParentScene = rootPrim._parent_scene;
163 m_timestep = _pParentScene.ODE_STEPSIZE;
164 m_invtimestep = 1.0f / m_timestep;
165 m_gravmod = rootPrim.GravModifier;
166 }
167
168 public void DoSetVehicle(VehicleData vd)
169 {
170 m_type = vd.m_type;
171 m_flags = vd.m_flags;
172
173
174 // Linear properties
175 m_linearMotorDirection = vd.m_linearMotorDirection;
176
177 m_linearFrictionTimescale = vd.m_linearFrictionTimescale;
178 if (m_linearFrictionTimescale.X < m_timestep) m_linearFrictionTimescale.X = m_timestep;
179 if (m_linearFrictionTimescale.Y < m_timestep) m_linearFrictionTimescale.Y = m_timestep;
180 if (m_linearFrictionTimescale.Z < m_timestep) m_linearFrictionTimescale.Z = m_timestep;
181
182 m_linearMotorDecayTimescale = vd.m_linearMotorDecayTimescale;
183 if (m_linearMotorDecayTimescale < m_timestep) m_linearMotorDecayTimescale = m_timestep;
184 m_linearMotorDecayTimescale += 0.2f;
185 m_linearMotorDecayTimescale *= m_invtimestep;
186
187 m_linearMotorTimescale = vd.m_linearMotorTimescale;
188 if (m_linearMotorTimescale < m_timestep) m_linearMotorTimescale = m_timestep;
189
190 m_linearMotorOffset = vd.m_linearMotorOffset;
191
192 //Angular properties
193 m_angularMotorDirection = vd.m_angularMotorDirection;
194 m_angularMotorTimescale = vd.m_angularMotorTimescale;
195 if (m_angularMotorTimescale < m_timestep) m_angularMotorTimescale = m_timestep;
196
197 m_angularMotorDecayTimescale = vd.m_angularMotorDecayTimescale;
198 if (m_angularMotorDecayTimescale < m_timestep) m_angularMotorDecayTimescale = m_timestep;
199 m_angularMotorDecayTimescale *= m_invtimestep;
200
201 m_angularFrictionTimescale = vd.m_angularFrictionTimescale;
202 if (m_angularFrictionTimescale.X < m_timestep) m_angularFrictionTimescale.X = m_timestep;
203 if (m_angularFrictionTimescale.Y < m_timestep) m_angularFrictionTimescale.Y = m_timestep;
204 if (m_angularFrictionTimescale.Z < m_timestep) m_angularFrictionTimescale.Z = m_timestep;
205
206 //Deflection properties
207 m_angularDeflectionEfficiency = vd.m_angularDeflectionEfficiency;
208 m_angularDeflectionTimescale = vd.m_angularDeflectionTimescale;
209 if (m_angularDeflectionTimescale < m_timestep) m_angularDeflectionTimescale = m_timestep;
210
211 m_linearDeflectionEfficiency = vd.m_linearDeflectionEfficiency;
212 m_linearDeflectionTimescale = vd.m_linearDeflectionTimescale;
213 if (m_linearDeflectionTimescale < m_timestep) m_linearDeflectionTimescale = m_timestep;
214
215 //Banking properties
216 m_bankingEfficiency = vd.m_bankingEfficiency;
217 m_bankingMix = vd.m_bankingMix;
218 m_bankingTimescale = vd.m_bankingTimescale;
219 if (m_bankingTimescale < m_timestep) m_bankingTimescale = m_timestep;
220
221 //Hover and Buoyancy properties
222 m_VhoverHeight = vd.m_VhoverHeight;
223 m_VhoverEfficiency = vd.m_VhoverEfficiency;
224 m_VhoverTimescale = vd.m_VhoverTimescale;
225 if (m_VhoverTimescale < m_timestep) m_VhoverTimescale = m_timestep;
226
227 m_VehicleBuoyancy = vd.m_VehicleBuoyancy;
228
229 //Attractor properties
230 m_verticalAttractionEfficiency = vd.m_verticalAttractionEfficiency;
231 m_verticalAttractionTimescale = vd.m_verticalAttractionTimescale;
232 if (m_verticalAttractionTimescale < m_timestep) m_verticalAttractionTimescale = m_timestep;
233
234 // Axis
235 m_referenceFrame = vd.m_referenceFrame;
236
237 m_lmEfect = 0;
238 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
239 m_amEfect = 0;
240 m_ffactor = 1.0f;
241 }
242
243 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
244 {
245 float len;
246
247 switch (pParam)
248 {
249 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
250 if (pValue < 0f) pValue = 0f;
251 if (pValue > 1f) pValue = 1f;
252 m_angularDeflectionEfficiency = pValue;
253 break;
254 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
255 if (pValue < m_timestep) pValue = m_timestep;
256 m_angularDeflectionTimescale = pValue;
257 break;
258 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
259 if (pValue < m_timestep) pValue = m_timestep;
260 else if (pValue > 120) pValue = 120;
261 m_angularMotorDecayTimescale = pValue * m_invtimestep;
262 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
263 break;
264 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
265 if (pValue < m_timestep) pValue = m_timestep;
266 m_angularMotorTimescale = pValue;
267 break;
268 case Vehicle.BANKING_EFFICIENCY:
269 if (pValue < -1f) pValue = -1f;
270 if (pValue > 1f) pValue = 1f;
271 m_bankingEfficiency = pValue;
272 break;
273 case Vehicle.BANKING_MIX:
274 if (pValue < 0f) pValue = 0f;
275 if (pValue > 1f) pValue = 1f;
276 m_bankingMix = pValue;
277 break;
278 case Vehicle.BANKING_TIMESCALE:
279 if (pValue < m_timestep) pValue = m_timestep;
280 m_bankingTimescale = pValue;
281 break;
282 case Vehicle.BUOYANCY:
283 if (pValue < -1f) pValue = -1f;
284 if (pValue > 1f) pValue = 1f;
285 m_VehicleBuoyancy = pValue;
286 break;
287 case Vehicle.HOVER_EFFICIENCY:
288 if (pValue < 0f) pValue = 0f;
289 if (pValue > 1f) pValue = 1f;
290 m_VhoverEfficiency = pValue;
291 break;
292 case Vehicle.HOVER_HEIGHT:
293 m_VhoverHeight = pValue;
294 break;
295 case Vehicle.HOVER_TIMESCALE:
296 if (pValue < m_timestep) pValue = m_timestep;
297 m_VhoverTimescale = pValue;
298 break;
299 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
300 if (pValue < 0f) pValue = 0f;
301 if (pValue > 1f) pValue = 1f;
302 m_linearDeflectionEfficiency = pValue;
303 break;
304 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
305 if (pValue < m_timestep) pValue = m_timestep;
306 m_linearDeflectionTimescale = pValue;
307 break;
308 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
309 if (pValue < m_timestep) pValue = m_timestep;
310 else if (pValue > 120) pValue = 120;
311 m_linearMotorDecayTimescale = (0.2f +pValue) * m_invtimestep;
312 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
313 break;
314 case Vehicle.LINEAR_MOTOR_TIMESCALE:
315 if (pValue < m_timestep) pValue = m_timestep;
316 m_linearMotorTimescale = pValue;
317 break;
318 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
319 if (pValue < 0f) pValue = 0f;
320 if (pValue > 1f) pValue = 1f;
321 m_verticalAttractionEfficiency = pValue;
322 break;
323 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
324 if (pValue < m_timestep) pValue = m_timestep;
325 m_verticalAttractionTimescale = pValue;
326 break;
327
328 // These are vector properties but the engine lets you use a single float value to
329 // set all of the components to the same value
330 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
331 if (pValue < m_timestep) pValue = m_timestep;
332 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
333 break;
334 case Vehicle.ANGULAR_MOTOR_DIRECTION:
335 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
336 len = m_angularMotorDirection.Length();
337 if (len > 12.566f)
338 m_angularMotorDirection *= (12.566f / len);
339
340 m_amEfect = 1.0f ; // turn it on
341 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
342
343 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
344 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
345 d.BodyEnable(rootPrim.Body);
346 break;
347 case Vehicle.LINEAR_FRICTION_TIMESCALE:
348 if (pValue < m_timestep) pValue = m_timestep;
349 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
350 break;
351 case Vehicle.LINEAR_MOTOR_DIRECTION:
352 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
353 len = m_linearMotorDirection.Length();
354 if (len > 100.0f)
355 m_linearMotorDirection *= (100.0f / len);
356
357 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
358 m_lmEfect = 1.0f; // turn it on
359
360 m_ffactor = 0.0f;
361 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
362 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
363 d.BodyEnable(rootPrim.Body);
364 break;
365 case Vehicle.LINEAR_MOTOR_OFFSET:
366 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
367 len = m_linearMotorOffset.Length();
368 if (len > 100.0f)
369 m_linearMotorOffset *= (100.0f / len);
370 break;
371 }
372 }//end ProcessFloatVehicleParam
373
374 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
375 {
376 float len;
377
378 switch (pParam)
379 {
380 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
381 if (pValue.X < m_timestep) pValue.X = m_timestep;
382 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
383 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
384
385 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
386 break;
387 case Vehicle.ANGULAR_MOTOR_DIRECTION:
388 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
389 // Limit requested angular speed to 2 rps= 4 pi rads/sec
390 len = m_angularMotorDirection.Length();
391 if (len > 12.566f)
392 m_angularMotorDirection *= (12.566f / len);
393
394 m_amEfect = 1.0f; // turn it on
395 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
396
397 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
398 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
399 d.BodyEnable(rootPrim.Body);
400 break;
401 case Vehicle.LINEAR_FRICTION_TIMESCALE:
402 if (pValue.X < m_timestep) pValue.X = m_timestep;
403 if (pValue.Y < m_timestep) pValue.Y = m_timestep;
404 if (pValue.Z < m_timestep) pValue.Z = m_timestep;
405 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
406 break;
407 case Vehicle.LINEAR_MOTOR_DIRECTION:
408 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
409 len = m_linearMotorDirection.Length();
410 if (len > 100.0f)
411 m_linearMotorDirection *= (100.0f / len);
412
413 m_lmEfect = 1.0f; // turn it on
414 m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale;
415
416 m_ffactor = 0.0f;
417 if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body)
418 && !rootPrim.m_isSelected && !rootPrim.m_disabled)
419 d.BodyEnable(rootPrim.Body);
420 break;
421 case Vehicle.LINEAR_MOTOR_OFFSET:
422 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
423 len = m_linearMotorOffset.Length();
424 if (len > 100.0f)
425 m_linearMotorOffset *= (100.0f / len);
426 break;
427 case Vehicle.BLOCK_EXIT:
428 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
429 break;
430 }
431 }//end ProcessVectorVehicleParam
432
433 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
434 {
435 switch (pParam)
436 {
437 case Vehicle.REFERENCE_FRAME:
438 // m_referenceFrame = Quaternion.Inverse(pValue);
439 m_referenceFrame = pValue;
440 break;
441 case Vehicle.ROLL_FRAME:
442 m_RollreferenceFrame = pValue;
443 break;
444 }
445 }//end ProcessRotationVehicleParam
446
447 internal void ProcessVehicleFlags(int pParam, bool remove)
448 {
449 if (remove)
450 {
451 m_flags &= ~((VehicleFlag)pParam);
452 }
453 else
454 {
455 m_flags |= (VehicleFlag)pParam;
456 }
457 }//end ProcessVehicleFlags
458
459 internal void ProcessTypeChange(Vehicle pType)
460 {
461 m_lmEfect = 0;
462
463 m_amEfect = 0;
464 m_ffactor = 1f;
465
466 m_linearMotorDirection = Vector3.Zero;
467 m_angularMotorDirection = Vector3.Zero;
468
469 m_BlockingEndPoint = Vector3.Zero;
470 m_RollreferenceFrame = Quaternion.Identity;
471 m_linearMotorOffset = Vector3.Zero;
472
473 m_referenceFrame = Quaternion.Identity;
474
475 // Set Defaults For Type
476 m_type = pType;
477 switch (pType)
478 {
479 case Vehicle.TYPE_NONE:
480 m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
481 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
482 m_linearMotorTimescale = 1000;
483 m_linearMotorDecayTimescale = 120 * m_invtimestep;
484 m_angularMotorTimescale = 1000;
485 m_angularMotorDecayTimescale = 1000 * m_invtimestep;
486 m_VhoverHeight = 0;
487 m_VhoverEfficiency = 1;
488 m_VhoverTimescale = 1000;
489 m_VehicleBuoyancy = 0;
490 m_linearDeflectionEfficiency = 0;
491 m_linearDeflectionTimescale = 1000;
492 m_angularDeflectionEfficiency = 0;
493 m_angularDeflectionTimescale = 1000;
494 m_bankingEfficiency = 0;
495 m_bankingMix = 1;
496 m_bankingTimescale = 1000;
497 m_verticalAttractionEfficiency = 0;
498 m_verticalAttractionTimescale = 1000;
499
500 m_flags = (VehicleFlag)0;
501 break;
502
503 case Vehicle.TYPE_SLED:
504 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
505 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
506 m_linearMotorTimescale = 1000;
507 m_linearMotorDecayTimescale = 120 * m_invtimestep;
508 m_angularMotorTimescale = 1000;
509 m_angularMotorDecayTimescale = 120 * m_invtimestep;
510 m_VhoverHeight = 0;
511 m_VhoverEfficiency = 1;
512 m_VhoverTimescale = 10;
513 m_VehicleBuoyancy = 0;
514 m_linearDeflectionEfficiency = 1;
515 m_linearDeflectionTimescale = 1;
516 m_angularDeflectionEfficiency = 0;
517 m_angularDeflectionTimescale = 10;
518 m_verticalAttractionEfficiency = 1;
519 m_verticalAttractionTimescale = 1000;
520 m_bankingEfficiency = 0;
521 m_bankingMix = 1;
522 m_bankingTimescale = 10;
523 m_flags &=
524 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
525 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
526 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
527 VehicleFlag.LIMIT_ROLL_ONLY |
528 VehicleFlag.LIMIT_MOTOR_UP);
529 break;
530
531 case Vehicle.TYPE_CAR:
532 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
533 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
534 m_linearMotorTimescale = 1;
535 m_linearMotorDecayTimescale = 60 * m_invtimestep;
536 m_angularMotorTimescale = 1;
537 m_angularMotorDecayTimescale = 0.8f * m_invtimestep;
538 m_VhoverHeight = 0;
539 m_VhoverEfficiency = 0;
540 m_VhoverTimescale = 1000;
541 m_VehicleBuoyancy = 0;
542 m_linearDeflectionEfficiency = 1;
543 m_linearDeflectionTimescale = 2;
544 m_angularDeflectionEfficiency = 0;
545 m_angularDeflectionTimescale = 10;
546 m_verticalAttractionEfficiency = 1f;
547 m_verticalAttractionTimescale = 10f;
548 m_bankingEfficiency = -0.2f;
549 m_bankingMix = 1;
550 m_bankingTimescale = 1;
551 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
552 VehicleFlag.HOVER_TERRAIN_ONLY |
553 VehicleFlag.HOVER_GLOBAL_HEIGHT);
554 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
555 VehicleFlag.LIMIT_ROLL_ONLY |
556 VehicleFlag.LIMIT_MOTOR_UP |
557 VehicleFlag.HOVER_UP_ONLY);
558 break;
559 case Vehicle.TYPE_BOAT:
560 m_linearFrictionTimescale = new Vector3(10, 3, 2);
561 m_angularFrictionTimescale = new Vector3(10, 10, 10);
562 m_linearMotorTimescale = 5;
563 m_linearMotorDecayTimescale = 60 * m_invtimestep;
564 m_angularMotorTimescale = 4;
565 m_angularMotorDecayTimescale = 4 * m_invtimestep;
566 m_VhoverHeight = 0;
567 m_VhoverEfficiency = 0.5f;
568 m_VhoverTimescale = 2;
569 m_VehicleBuoyancy = 1;
570 m_linearDeflectionEfficiency = 0.5f;
571 m_linearDeflectionTimescale = 3;
572 m_angularDeflectionEfficiency = 0.5f;
573 m_angularDeflectionTimescale = 5;
574 m_verticalAttractionEfficiency = 0.5f;
575 m_verticalAttractionTimescale = 5f;
576 m_bankingEfficiency = -0.3f;
577 m_bankingMix = 0.8f;
578 m_bankingTimescale = 1;
579 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
580 VehicleFlag.HOVER_GLOBAL_HEIGHT |
581 VehicleFlag.HOVER_UP_ONLY); // |
582// VehicleFlag.LIMIT_ROLL_ONLY);
583 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
584 VehicleFlag.LIMIT_MOTOR_UP |
585 VehicleFlag.HOVER_UP_ONLY | // new sl
586 VehicleFlag.HOVER_WATER_ONLY);
587 break;
588
589 case Vehicle.TYPE_AIRPLANE:
590 m_linearFrictionTimescale = new Vector3(200, 10, 5);
591 m_angularFrictionTimescale = new Vector3(20, 20, 20);
592 m_linearMotorTimescale = 2;
593 m_linearMotorDecayTimescale = 60 * m_invtimestep;
594 m_angularMotorTimescale = 4;
595 m_angularMotorDecayTimescale = 8 * m_invtimestep;
596 m_VhoverHeight = 0;
597 m_VhoverEfficiency = 0.5f;
598 m_VhoverTimescale = 1000;
599 m_VehicleBuoyancy = 0;
600 m_linearDeflectionEfficiency = 0.5f;
601 m_linearDeflectionTimescale = 0.5f;
602 m_angularDeflectionEfficiency = 1;
603 m_angularDeflectionTimescale = 2;
604 m_verticalAttractionEfficiency = 0.9f;
605 m_verticalAttractionTimescale = 2f;
606 m_bankingEfficiency = 1;
607 m_bankingMix = 0.7f;
608 m_bankingTimescale = 2;
609 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
610 VehicleFlag.HOVER_TERRAIN_ONLY |
611 VehicleFlag.HOVER_GLOBAL_HEIGHT |
612 VehicleFlag.HOVER_UP_ONLY |
613 VehicleFlag.NO_DEFLECTION_UP |
614 VehicleFlag.LIMIT_MOTOR_UP);
615 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
616 break;
617
618 case Vehicle.TYPE_BALLOON:
619 m_linearFrictionTimescale = new Vector3(5, 5, 5);
620 m_angularFrictionTimescale = new Vector3(10, 10, 10);
621 m_linearMotorTimescale = 5;
622 m_linearMotorDecayTimescale = 60 * m_invtimestep;
623 m_angularMotorTimescale = 6;
624 m_angularMotorDecayTimescale = 10 * m_invtimestep;
625 m_VhoverHeight = 5;
626 m_VhoverEfficiency = 0.8f;
627 m_VhoverTimescale = 10;
628 m_VehicleBuoyancy = 1;
629 m_linearDeflectionEfficiency = 0;
630 m_linearDeflectionTimescale = 5 * m_invtimestep;
631 m_angularDeflectionEfficiency = 0;
632 m_angularDeflectionTimescale = 5;
633 m_verticalAttractionEfficiency = 1f;
634 m_verticalAttractionTimescale = 1000f;
635 m_bankingEfficiency = 0;
636 m_bankingMix = 0.7f;
637 m_bankingTimescale = 5;
638 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
639 VehicleFlag.HOVER_TERRAIN_ONLY |
640 VehicleFlag.HOVER_UP_ONLY |
641 VehicleFlag.NO_DEFLECTION_UP |
642 VehicleFlag.LIMIT_MOTOR_UP | //);
643 VehicleFlag.LIMIT_ROLL_ONLY | // new sl
644 VehicleFlag.HOVER_GLOBAL_HEIGHT); // new sl
645
646// m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
647// VehicleFlag.HOVER_GLOBAL_HEIGHT);
648 break;
649
650 }
651
652 m_lmDecay = (1.0f - 1.0f / m_linearMotorDecayTimescale);
653 m_amDecay = 1.0f - 1.0f / m_angularMotorDecayTimescale;
654
655 }//end SetDefaultsForType
656
657 internal void Stop()
658 {
659 m_lmEfect = 0;
660 m_lmDecay = 0f;
661 m_amEfect = 0;
662 m_amDecay = 0;
663 m_ffactor = 1f;
664 }
665
666 public static Vector3 Xrot(Quaternion rot)
667 {
668 Vector3 vec;
669 rot.Normalize(); // just in case
670 vec.X = 2 * (rot.X * rot.X + rot.W * rot.W) - 1;
671 vec.Y = 2 * (rot.X * rot.Y + rot.Z * rot.W);
672 vec.Z = 2 * (rot.X * rot.Z - rot.Y * rot.W);
673 return vec;
674 }
675
676 public static Vector3 Zrot(Quaternion rot)
677 {
678 Vector3 vec;
679 rot.Normalize(); // just in case
680 vec.X = 2 * (rot.X * rot.Z + rot.Y * rot.W);
681 vec.Y = 2 * (rot.Y * rot.Z - rot.X * rot.W);
682 vec.Z = 2 * (rot.Z * rot.Z + rot.W * rot.W) - 1;
683
684 return vec;
685 }
686
687 private const float pi = (float)Math.PI;
688 private const float halfpi = 0.5f * (float)Math.PI;
689 private const float twopi = 2.0f * pi;
690
691 public static Vector3 ubRot2Euler(Quaternion rot)
692 {
693 // returns roll in X
694 // pitch in Y
695 // yaw in Z
696 Vector3 vec;
697
698 // assuming rot is normalised
699 // rot.Normalize();
700
701 float zX = rot.X * rot.Z + rot.Y * rot.W;
702
703 if (zX < -0.49999f)
704 {
705 vec.X = 0;
706 vec.Y = -halfpi;
707 vec.Z = (float)(-2d * Math.Atan(rot.X / rot.W));
708 }
709 else if (zX > 0.49999f)
710 {
711 vec.X = 0;
712 vec.Y = halfpi;
713 vec.Z = (float)(2d * Math.Atan(rot.X / rot.W));
714 }
715 else
716 {
717 vec.Y = (float)Math.Asin(2 * zX);
718
719 float sqw = rot.W * rot.W;
720
721 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
722 float zZ = rot.Z * rot.Z + sqw - 0.5f;
723
724 vec.X = (float)Math.Atan2(minuszY, zZ);
725
726 float yX = rot.Z * rot.W - rot.X * rot.Y; //( have negative ?)
727 float yY = rot.X * rot.X + sqw - 0.5f;
728 vec.Z = (float)Math.Atan2(yX, yY);
729 }
730 return vec;
731 }
732
733 public static void GetRollPitch(Quaternion rot, out float roll, out float pitch)
734 {
735 // assuming rot is normalised
736 // rot.Normalize();
737
738 float zX = rot.X * rot.Z + rot.Y * rot.W;
739
740 if (zX < -0.49999f)
741 {
742 roll = 0;
743 pitch = -halfpi;
744 }
745 else if (zX > 0.49999f)
746 {
747 roll = 0;
748 pitch = halfpi;
749 }
750 else
751 {
752 pitch = (float)Math.Asin(2 * zX);
753
754 float minuszY = rot.X * rot.W - rot.Y * rot.Z;
755 float zZ = rot.Z * rot.Z + rot.W * rot.W - 0.5f;
756
757 roll = (float)Math.Atan2(minuszY, zZ);
758 }
759 return ;
760 }
761
762 internal void Step()
763 {
764 IntPtr Body = rootPrim.Body;
765
766 d.Mass dmass;
767 d.BodyGetMass(Body, out dmass);
768
769 d.Quaternion rot = d.BodyGetQuaternion(Body);
770 Quaternion objrotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object
771 Quaternion rotq = objrotq; // rotq = rotation of object
772 rotq *= m_referenceFrame; // rotq is now rotation in vehicle reference frame
773 Quaternion irotq = Quaternion.Inverse(rotq);
774
775 d.Vector3 dvtmp;
776 Vector3 tmpV;
777 Vector3 curVel; // velocity in world
778 Vector3 curAngVel; // angular velocity in world
779 Vector3 force = Vector3.Zero; // actually linear aceleration until mult by mass in world frame
780 Vector3 torque = Vector3.Zero;// actually angular aceleration until mult by Inertia in vehicle frame
781 d.Vector3 dtorque = new d.Vector3();
782
783 dvtmp = d.BodyGetLinearVel(Body);
784 curVel.X = dvtmp.X;
785 curVel.Y = dvtmp.Y;
786 curVel.Z = dvtmp.Z;
787 Vector3 curLocalVel = curVel * irotq; // current velocity in local
788
789 dvtmp = d.BodyGetAngularVel(Body);
790 curAngVel.X = dvtmp.X;
791 curAngVel.Y = dvtmp.Y;
792 curAngVel.Z = dvtmp.Z;
793 Vector3 curLocalAngVel = curAngVel * irotq; // current angular velocity in local
794
795 float ldampZ = 0;
796
797 // linear motor
798 if (m_lmEfect > 0.01 && m_linearMotorTimescale < 1000)
799 {
800 tmpV = m_linearMotorDirection - curLocalVel; // velocity error
801 tmpV *= m_lmEfect / m_linearMotorTimescale; // error to correct in this timestep
802 tmpV *= rotq; // to world
803
804 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0)
805 tmpV.Z = 0;
806
807 if (m_linearMotorOffset.X != 0 || m_linearMotorOffset.Y != 0 || m_linearMotorOffset.Z != 0)
808 {
809 // have offset, do it now
810 tmpV *= dmass.mass;
811 d.BodyAddForceAtRelPos(Body, tmpV.X, tmpV.Y, tmpV.Z, m_linearMotorOffset.X, m_linearMotorOffset.Y, m_linearMotorOffset.Z);
812 }
813 else
814 {
815 force.X += tmpV.X;
816 force.Y += tmpV.Y;
817 force.Z += tmpV.Z;
818 }
819
820 m_lmEfect *= m_lmDecay;
821// m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared();
822 m_ffactor = 0.0f;
823 }
824 else
825 {
826 m_lmEfect = 0;
827 m_ffactor = 1f;
828 }
829
830 // hover
831 if (m_VhoverTimescale < 300 && rootPrim.prim_geom != IntPtr.Zero)
832 {
833 // d.Vector3 pos = d.BodyGetPosition(Body);
834 d.Vector3 pos = d.GeomGetPosition(rootPrim.prim_geom);
835 pos.Z -= 0.21f; // minor offset that seems to be always there in sl
836
837 float t = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y);
838 float perr;
839
840 // default to global but don't go underground
841 perr = m_VhoverHeight - pos.Z;
842
843 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == 0)
844 {
845 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
846 {
847 perr += _pParentScene.GetWaterLevel();
848 }
849 else if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
850 {
851 perr += t;
852 }
853 else
854 {
855 float w = _pParentScene.GetWaterLevel();
856 if (t > w)
857 perr += t;
858 else
859 perr += w;
860 }
861 }
862 else if (t > m_VhoverHeight)
863 perr = t - pos.Z; ;
864
865 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) == 0 || perr > -0.1)
866 {
867 ldampZ = m_VhoverEfficiency * m_invtimestep;
868
869 perr *= (1.0f + ldampZ) / m_VhoverTimescale;
870
871 // force.Z += perr - curVel.Z * tmp;
872 force.Z += perr;
873 ldampZ *= -curVel.Z;
874
875 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
876 }
877 else // no buoyancy
878 force.Z += _pParentScene.gravityz;
879 }
880 else
881 {
882 // default gravity and Buoyancy
883 force.Z += _pParentScene.gravityz * m_gravmod * (1f - m_VehicleBuoyancy);
884 }
885
886 // linear deflection
887 if (m_linearDeflectionEfficiency > 0)
888 {
889 float len = curVel.Length();
890 if (len > 0.01) // if moving
891 {
892 Vector3 atAxis;
893 atAxis = Xrot(rotq); // where are we pointing to
894 atAxis *= len; // make it same size as world velocity vector
895
896 tmpV = -atAxis; // oposite direction
897 atAxis -= curVel; // error to one direction
898 len = atAxis.LengthSquared();
899
900 tmpV -= curVel; // error to oposite
901 float lens = tmpV.LengthSquared();
902
903 if (len > 0.01 || lens > 0.01) // do nothing if close enougth
904 {
905 if (len < lens)
906 tmpV = atAxis;
907
908 tmpV *= (m_linearDeflectionEfficiency / m_linearDeflectionTimescale); // error to correct in this timestep
909 force.X += tmpV.X;
910 force.Y += tmpV.Y;
911 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) == 0)
912 force.Z += tmpV.Z;
913 }
914 }
915 }
916
917 // linear friction/damping
918 if (curLocalVel.X != 0 || curLocalVel.Y != 0 || curLocalVel.Z != 0)
919 {
920 tmpV.X = -curLocalVel.X / m_linearFrictionTimescale.X;
921 tmpV.Y = -curLocalVel.Y / m_linearFrictionTimescale.Y;
922 tmpV.Z = -curLocalVel.Z / m_linearFrictionTimescale.Z;
923 tmpV *= rotq; // to world
924
925 if(ldampZ != 0 && Math.Abs(ldampZ) > Math.Abs(tmpV.Z))
926 tmpV.Z = ldampZ;
927 force.X += tmpV.X;
928 force.Y += tmpV.Y;
929 force.Z += tmpV.Z;
930 }
931
932 // vertical atractor
933 if (m_verticalAttractionTimescale < 300)
934 {
935 float roll;
936 float pitch;
937
938
939
940 float ftmp = m_invtimestep / m_verticalAttractionTimescale / m_verticalAttractionTimescale;
941
942 float ftmp2;
943 ftmp2 = 0.5f * m_verticalAttractionEfficiency * m_invtimestep;
944 m_amdampX = ftmp2;
945
946 m_ampwr = 1.0f - 0.8f * m_verticalAttractionEfficiency;
947
948 GetRollPitch(irotq, out roll, out pitch);
949
950 if (roll > halfpi)
951 roll = pi - roll;
952 else if (roll < -halfpi)
953 roll = -pi - roll;
954
955 float effroll = pitch / halfpi;
956 effroll *= effroll;
957 effroll = 1 - effroll;
958 effroll *= roll;
959
960
961 torque.X += effroll * ftmp;
962
963 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) == 0)
964 {
965 float effpitch = roll / halfpi;
966 effpitch *= effpitch;
967 effpitch = 1 - effpitch;
968 effpitch *= pitch;
969
970 torque.Y += effpitch * ftmp;
971 }
972
973 if (m_bankingEfficiency != 0 && Math.Abs(effroll) > 0.01)
974 {
975
976 float broll = effroll;
977 /*
978 if (broll > halfpi)
979 broll = pi - broll;
980 else if (broll < -halfpi)
981 broll = -pi - broll;
982 */
983 broll *= m_bankingEfficiency;
984 if (m_bankingMix != 0)
985 {
986 float vfact = Math.Abs(curLocalVel.X) / 10.0f;
987 if (vfact > 1.0f) vfact = 1.0f;
988
989 if (curLocalVel.X >= 0)
990 broll *= (1 + (vfact - 1) * m_bankingMix);
991 else
992 broll *= -(1 + (vfact - 1) * m_bankingMix);
993 }
994 // make z rot be in world Z not local as seems to be in sl
995
996 broll = broll / m_bankingTimescale;
997
998
999 tmpV = Zrot(irotq);
1000 tmpV *= broll;
1001
1002 torque.X += tmpV.X;
1003 torque.Y += tmpV.Y;
1004 torque.Z += tmpV.Z;
1005
1006 m_amdampZ = Math.Abs(m_bankingEfficiency) / m_bankingTimescale;
1007 m_amdampY = m_amdampZ;
1008
1009 }
1010 else
1011 {
1012 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1013 m_amdampY = m_amdampX;
1014 }
1015 }
1016 else
1017 {
1018 m_ampwr = 1.0f;
1019 m_amdampX = 1 / m_angularFrictionTimescale.X;
1020 m_amdampY = 1 / m_angularFrictionTimescale.Y;
1021 m_amdampZ = 1 / m_angularFrictionTimescale.Z;
1022 }
1023
1024 // angular motor
1025 if (m_amEfect > 0.01 && m_angularMotorTimescale < 1000)
1026 {
1027 tmpV = m_angularMotorDirection - curLocalAngVel; // velocity error
1028 tmpV *= m_amEfect / m_angularMotorTimescale; // error to correct in this timestep
1029 torque.X += tmpV.X * m_ampwr;
1030 torque.Y += tmpV.Y * m_ampwr;
1031 torque.Z += tmpV.Z;
1032
1033 m_amEfect *= m_amDecay;
1034 }
1035 else
1036 m_amEfect = 0;
1037
1038 // angular deflection
1039 if (m_angularDeflectionEfficiency > 0)
1040 {
1041 Vector3 dirv;
1042
1043 if (curLocalVel.X > 0.01f)
1044 dirv = curLocalVel;
1045 else if (curLocalVel.X < -0.01f)
1046 // use oposite
1047 dirv = -curLocalVel;
1048 else
1049 {
1050 // make it fall into small positive x case
1051 dirv.X = 0.01f;
1052 dirv.Y = curLocalVel.Y;
1053 dirv.Z = curLocalVel.Z;
1054 }
1055
1056 float ftmp = m_angularDeflectionEfficiency / m_angularDeflectionTimescale;
1057
1058 if (Math.Abs(dirv.Z) > 0.01)
1059 {
1060 torque.Y += - (float)Math.Atan2(dirv.Z, dirv.X) * ftmp;
1061 }
1062
1063 if (Math.Abs(dirv.Y) > 0.01)
1064 {
1065 torque.Z += (float)Math.Atan2(dirv.Y, dirv.X) * ftmp;
1066 }
1067 }
1068
1069 // angular friction
1070 if (curLocalAngVel.X != 0 || curLocalAngVel.Y != 0 || curLocalAngVel.Z != 0)
1071 {
1072 torque.X -= curLocalAngVel.X * m_amdampX;
1073 torque.Y -= curLocalAngVel.Y * m_amdampY;
1074 torque.Z -= curLocalAngVel.Z * m_amdampZ;
1075 }
1076
1077
1078 if (force.X != 0 || force.Y != 0 || force.Z != 0)
1079 {
1080 force *= dmass.mass;
1081 d.BodyAddForce(Body, force.X, force.Y, force.Z);
1082 }
1083
1084 if (torque.X != 0 || torque.Y != 0 || torque.Z != 0)
1085 {
1086 torque *= m_referenceFrame; // to object frame
1087 dtorque.X = torque.X ;
1088 dtorque.Y = torque.Y;
1089 dtorque.Z = torque.Z;
1090
1091 d.MultiplyM3V3(out dvtmp, ref dmass.I, ref dtorque);
1092 d.BodyAddRelTorque(Body, dvtmp.X, dvtmp.Y, dvtmp.Z); // add torque in object frame
1093 }
1094 }
1095 }
1096}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
new file mode 100644
index 0000000..40b5ef7
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs
@@ -0,0 +1,933 @@
1/*
2 * AJLDuarte 2012
3 */
4
5using System;
6using System.Threading;
7using System.Collections.Generic;
8using System.IO;
9using System.Reflection;
10using System.Runtime.InteropServices;
11using System.Text;
12using OpenSim.Framework;
13using OpenSim.Region.PhysicsModules.SharedBase;
14using OdeAPI;
15using log4net;
16using Nini.Config;
17using OpenMetaverse;
18
19namespace OpenSim.Region.PhysicsModule.ubOde
20{
21 public enum MeshState : byte
22 {
23 noNeed = 0,
24
25 loadingAsset = 1,
26
27 AssetOK = 0x0f, // 00001111
28
29 NeedMask = 0x30, // 00110000
30 needMesh = 0x10, // 00010000
31 needAsset = 0x20, // 00100000
32
33 FailMask = 0xC0, // 11000000
34 AssetFailed = 0x40, // 01000000
35 MeshFailed = 0x80, // 10000000
36
37 MeshNoColide = FailMask | needAsset
38 }
39
40 public enum meshWorkerCmnds : byte
41 {
42 nop = 0,
43 addnew,
44 changefull,
45 changesize,
46 changeshapetype,
47 getmesh,
48 }
49
50 public class ODEPhysRepData
51 {
52 public PhysicsActor actor;
53 public PrimitiveBaseShape pbs;
54 public IMesh mesh;
55
56 public Vector3 size;
57 public Vector3 OBB;
58 public Vector3 OBBOffset;
59
60 public float volume;
61
62 public byte shapetype;
63 public bool hasOBB;
64 public bool hasMeshVolume;
65 public MeshState meshState;
66 public UUID? assetID;
67 public meshWorkerCmnds comand;
68 }
69
70 public class ODEMeshWorker
71 {
72
73 private ILog m_log;
74 private ODEScene m_scene;
75 private IMesher m_mesher;
76
77 public bool meshSculptedPrim = true;
78 public bool forceSimplePrimMeshing = false;
79 public float meshSculptLOD = 32;
80 public float MeshSculptphysicalLOD = 32;
81
82
83 private OpenSim.Framework.BlockingQueue<ODEPhysRepData> createqueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
84 private bool m_running;
85
86 private Thread m_thread;
87
88 public ODEMeshWorker(ODEScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
89 {
90 m_scene = pScene;
91 m_log = pLog;
92 m_mesher = pMesher;
93
94 if (pConfig != null)
95 {
96 forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
97 meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
98 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
99 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
100 }
101 m_running = true;
102 m_thread = new Thread(DoWork);
103 m_thread.Name = "OdeMeshWorker";
104 m_thread.Start();
105 }
106
107 private void DoWork()
108 {
109 m_mesher.ExpireFileCache();
110
111 while(m_running)
112 {
113 ODEPhysRepData nextRep = createqueue.Dequeue();
114 if(!m_running)
115 return;
116 if (nextRep == null)
117 continue;
118 if (m_scene.haveActor(nextRep.actor))
119 {
120 switch (nextRep.comand)
121 {
122 case meshWorkerCmnds.changefull:
123 case meshWorkerCmnds.changeshapetype:
124 case meshWorkerCmnds.changesize:
125 GetMesh(nextRep);
126 if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
127 m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
128 break;
129 case meshWorkerCmnds.getmesh:
130 DoRepDataGetMesh(nextRep);
131 break;
132 }
133 }
134 }
135 }
136
137 public void Stop()
138 {
139 try
140 {
141 m_thread.Abort();
142 createqueue.Clear();
143 }
144 catch
145 {
146 }
147 }
148
149 public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
150 Vector3 size, byte shapetype)
151 {
152 ODEPhysRepData repData = new ODEPhysRepData();
153 repData.actor = actor;
154 repData.pbs = pbs;
155 repData.size = size;
156 repData.shapetype = shapetype;
157
158 CheckMesh(repData);
159 CalcVolumeData(repData);
160 m_scene.AddChange(actor, changes.PhysRepData, repData);
161 return;
162 }
163
164 public ODEPhysRepData NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
165 Vector3 size, byte shapetype)
166 {
167 ODEPhysRepData repData = new ODEPhysRepData();
168 repData.actor = actor;
169 repData.pbs = pbs;
170 repData.size = size;
171 repData.shapetype = shapetype;
172
173 CheckMesh(repData);
174 CalcVolumeData(repData);
175 m_scene.AddChange(actor, changes.AddPhysRep, repData);
176 return repData;
177 }
178
179 public void RequestMesh(ODEPhysRepData repData)
180 {
181 repData.mesh = null;
182
183 if (repData.meshState == MeshState.needAsset)
184 {
185 PrimitiveBaseShape pbs = repData.pbs;
186
187 // check if we got outdated
188
189 if (!pbs.SculptEntry || pbs.SculptTexture == UUID.Zero)
190 {
191 repData.meshState = MeshState.noNeed;
192 return;
193 }
194
195 repData.assetID = pbs.SculptTexture;
196 repData.meshState = MeshState.loadingAsset;
197
198 repData.comand = meshWorkerCmnds.getmesh;
199 createqueue.Enqueue(repData);
200 }
201 }
202
203 // creates and prepares a mesh to use and calls parameters estimation
204 public bool CreateActorPhysRep(ODEPhysRepData repData)
205 {
206 IMesh mesh = repData.mesh;
207
208 if (mesh != null)
209 {
210 IntPtr vertices, indices;
211 int vertexCount, indexCount;
212 int vertexStride, triStride;
213
214 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
215 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
216
217 if (vertexCount == 0 || indexCount == 0)
218 {
219 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
220 repData.actor.Name, repData.pbs.SculptTexture.ToString());
221 repData.meshState = MeshState.MeshFailed;
222 repData.hasOBB = false;
223 repData.mesh = null;
224 m_scene.mesher.ReleaseMesh(mesh);
225 }
226 else
227 {
228 repData.OBBOffset = mesh.GetCentroid();
229 repData.OBB = mesh.GetOBB();
230 repData.hasOBB = true;
231 mesh.releaseSourceMeshData();
232 }
233 }
234 CalcVolumeData(repData);
235 return true;
236 }
237
238 public void AssetLoaded(ODEPhysRepData repData)
239 {
240 if (m_scene.haveActor(repData.actor))
241 {
242 if (needsMeshing(repData.pbs)) // no need for pbs now?
243 {
244 repData.comand = meshWorkerCmnds.changefull;
245 createqueue.Enqueue(repData);
246 }
247 }
248 else
249 repData.pbs.SculptData = Utils.EmptyBytes;
250 }
251
252 public void DoRepDataGetMesh(ODEPhysRepData repData)
253 {
254 if (!repData.pbs.SculptEntry)
255 return;
256
257 if (repData.meshState != MeshState.loadingAsset)
258 return;
259
260 if (repData.assetID == null || repData.assetID == UUID.Zero)
261 return;
262
263 if (repData.assetID != repData.pbs.SculptTexture)
264 return;
265
266 // check if it is in cache
267 GetMesh(repData);
268 if (repData.meshState != MeshState.needAsset)
269 {
270 CreateActorPhysRep(repData);
271 m_scene.AddChange(repData.actor, changes.PhysRepData, repData);
272 return;
273 }
274
275 RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
276 if (assetProvider == null)
277 return;
278 ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
279 }
280
281
282 /// <summary>
283 /// Routine to figure out if we need to mesh this prim with our mesher
284 /// </summary>
285 /// <param name="pbs"></param>
286 /// <returns></returns>
287 public bool needsMeshing(PrimitiveBaseShape pbs)
288 {
289 // check sculpts or meshs
290 if (pbs.SculptEntry)
291 {
292 if (meshSculptedPrim)
293 return true;
294
295 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
296 return true;
297
298 return false;
299 }
300
301 if (forceSimplePrimMeshing)
302 return true;
303
304 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
305
306 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
307 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
308 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
309 {
310
311 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
312 && pbs.ProfileHollow == 0
313 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
314 && pbs.PathBegin == 0 && pbs.PathEnd == 0
315 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
316 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
317 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
318 {
319 return false;
320 }
321 }
322
323 // following code doesn't give meshs to boxes and spheres ever
324 // and it's odd.. so for now just return true if asked to force meshs
325 // hopefully mesher will fail if doesn't suport so things still get basic boxes
326
327 int iPropertiesNotSupportedDefault = 0;
328
329 if (pbs.ProfileHollow != 0)
330 iPropertiesNotSupportedDefault++;
331
332 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
333 iPropertiesNotSupportedDefault++;
334
335 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
336 iPropertiesNotSupportedDefault++;
337
338 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
339 iPropertiesNotSupportedDefault++;
340
341 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
342 iPropertiesNotSupportedDefault++;
343
344 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
345 iPropertiesNotSupportedDefault++;
346
347 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
348 iPropertiesNotSupportedDefault++;
349
350 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
351 iPropertiesNotSupportedDefault++;
352
353 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
354 iPropertiesNotSupportedDefault++;
355
356 // test for torus
357 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
358 {
359 if (pbs.PathCurve == (byte)Extrusion.Curve1)
360 {
361 iPropertiesNotSupportedDefault++;
362 }
363 }
364 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
365 {
366 if (pbs.PathCurve == (byte)Extrusion.Straight)
367 {
368 iPropertiesNotSupportedDefault++;
369 }
370
371 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
372 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
373 {
374 iPropertiesNotSupportedDefault++;
375 }
376 }
377 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
378 {
379 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
380 {
381 iPropertiesNotSupportedDefault++;
382 }
383 }
384 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
385 {
386 if (pbs.PathCurve == (byte)Extrusion.Straight)
387 {
388 iPropertiesNotSupportedDefault++;
389 }
390 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
391 {
392 iPropertiesNotSupportedDefault++;
393 }
394 }
395
396 if (iPropertiesNotSupportedDefault == 0)
397 {
398 return false;
399 }
400 return true;
401 }
402
403 // see if we need a mesh and if so if we have a cached one
404 // called with a new repData
405 public void CheckMesh(ODEPhysRepData repData)
406 {
407 PhysicsActor actor = repData.actor;
408 PrimitiveBaseShape pbs = repData.pbs;
409
410 if (!needsMeshing(pbs))
411 {
412 repData.meshState = MeshState.noNeed;
413 return;
414 }
415
416 IMesh mesh = null;
417
418 Vector3 size = repData.size;
419 byte shapetype = repData.shapetype;
420
421 bool convex;
422
423 int clod = (int)LevelOfDetail.High;
424 if (shapetype == 0)
425 convex = false;
426 else
427 {
428 convex = true;
429 if (pbs.SculptType != (byte)SculptType.Mesh)
430 clod = (int)LevelOfDetail.Low;
431 }
432
433 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
434
435 if (mesh == null)
436 {
437 if (pbs.SculptEntry)
438 {
439 if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
440 {
441 repData.assetID = pbs.SculptTexture;
442 repData.meshState = MeshState.needAsset;
443 }
444 else
445 repData.meshState = MeshState.MeshFailed;
446
447 return;
448 }
449 else
450 {
451 repData.meshState = MeshState.needMesh;
452 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
453 if (mesh == null)
454 {
455 repData.meshState = MeshState.MeshFailed;
456 return;
457 }
458 }
459 }
460
461 repData.meshState = MeshState.AssetOK;
462 repData.mesh = mesh;
463
464 if (pbs.SculptEntry)
465 {
466 repData.assetID = pbs.SculptTexture;
467 }
468
469 pbs.SculptData = Utils.EmptyBytes;
470 return ;
471 }
472
473 public void GetMesh(ODEPhysRepData repData)
474 {
475 PhysicsActor actor = repData.actor;
476
477 PrimitiveBaseShape pbs = repData.pbs;
478
479 repData.mesh = null;
480 repData.hasOBB = false;
481
482 if (!needsMeshing(pbs))
483 {
484 repData.meshState = MeshState.noNeed;
485 return;
486 }
487
488 if (repData.meshState == MeshState.MeshFailed)
489 return;
490
491 if (pbs.SculptEntry)
492 {
493 if (repData.meshState == MeshState.AssetFailed)
494 {
495 if (pbs.SculptTexture == repData.assetID)
496 return;
497 }
498 }
499
500 repData.meshState = MeshState.noNeed;
501
502 IMesh mesh = null;
503 Vector3 size = repData.size;
504 byte shapetype = repData.shapetype;
505
506 bool convex;
507 int clod = (int)LevelOfDetail.High;
508 if (shapetype == 0)
509 convex = false;
510 else
511 {
512 convex = true;
513 if (pbs.SculptType != (byte)SculptType.Mesh)
514 clod = (int)LevelOfDetail.Low;
515 }
516
517 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex, true);
518
519 if (mesh == null)
520 {
521 if (pbs.SculptEntry)
522 {
523 if (pbs.SculptTexture == UUID.Zero)
524 return;
525
526 repData.assetID = pbs.SculptTexture;
527
528 if (pbs.SculptData == null || pbs.SculptData.Length == 0)
529 {
530 repData.meshState = MeshState.needAsset;
531 return;
532 }
533 }
534 }
535
536 repData.mesh = mesh;
537 repData.pbs.SculptData = Utils.EmptyBytes;
538
539 if (mesh == null)
540 {
541 if (pbs.SculptEntry)
542 repData.meshState = MeshState.AssetFailed;
543 else
544 repData.meshState = MeshState.MeshFailed;
545
546 return;
547 }
548
549 repData.meshState = MeshState.AssetOK;
550
551 return;
552 }
553
554 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
555 {
556 PrimitiveBaseShape _pbs = repData.pbs;
557 Vector3 _size = repData.size;
558
559 float volume = _size.X * _size.Y * _size.Z; // default
560 float tmp;
561
562 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
563 float hollowVolume = hollowAmount * hollowAmount;
564
565 switch (_pbs.ProfileShape)
566 {
567 case ProfileShape.Square:
568 // default box
569
570 if (_pbs.PathCurve == (byte)Extrusion.Straight)
571 {
572 if (hollowAmount > 0.0)
573 {
574 switch (_pbs.HollowShape)
575 {
576 case HollowShape.Square:
577 case HollowShape.Same:
578 break;
579
580 case HollowShape.Circle:
581
582 hollowVolume *= 0.78539816339f;
583 break;
584
585 case HollowShape.Triangle:
586
587 hollowVolume *= (0.5f * .5f);
588 break;
589
590 default:
591 hollowVolume = 0;
592 break;
593 }
594 volume *= (1.0f - hollowVolume);
595 }
596 }
597
598 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
599 {
600 //a tube
601
602 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
603 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
604 volume -= volume * tmp * tmp;
605
606 if (hollowAmount > 0.0)
607 {
608 hollowVolume *= hollowAmount;
609
610 switch (_pbs.HollowShape)
611 {
612 case HollowShape.Square:
613 case HollowShape.Same:
614 break;
615
616 case HollowShape.Circle:
617 hollowVolume *= 0.78539816339f;
618 break;
619
620 case HollowShape.Triangle:
621 hollowVolume *= 0.5f * 0.5f;
622 break;
623 default:
624 hollowVolume = 0;
625 break;
626 }
627 volume *= (1.0f - hollowVolume);
628 }
629 }
630
631 break;
632
633 case ProfileShape.Circle:
634
635 if (_pbs.PathCurve == (byte)Extrusion.Straight)
636 {
637 volume *= 0.78539816339f; // elipse base
638
639 if (hollowAmount > 0.0)
640 {
641 switch (_pbs.HollowShape)
642 {
643 case HollowShape.Same:
644 case HollowShape.Circle:
645 break;
646
647 case HollowShape.Square:
648 hollowVolume *= 0.5f * 2.5984480504799f;
649 break;
650
651 case HollowShape.Triangle:
652 hollowVolume *= .5f * 1.27323954473516f;
653 break;
654
655 default:
656 hollowVolume = 0;
657 break;
658 }
659 volume *= (1.0f - hollowVolume);
660 }
661 }
662
663 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
664 {
665 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
666 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
667 volume *= (1.0f - tmp * tmp);
668
669 if (hollowAmount > 0.0)
670 {
671
672 // calculate the hollow volume by it's shape compared to the prim shape
673 hollowVolume *= hollowAmount;
674
675 switch (_pbs.HollowShape)
676 {
677 case HollowShape.Same:
678 case HollowShape.Circle:
679 break;
680
681 case HollowShape.Square:
682 hollowVolume *= 0.5f * 2.5984480504799f;
683 break;
684
685 case HollowShape.Triangle:
686 hollowVolume *= .5f * 1.27323954473516f;
687 break;
688
689 default:
690 hollowVolume = 0;
691 break;
692 }
693 volume *= (1.0f - hollowVolume);
694 }
695 }
696 break;
697
698 case ProfileShape.HalfCircle:
699 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
700 {
701 volume *= 0.5236f;
702
703 if (hollowAmount > 0.0)
704 {
705 hollowVolume *= hollowAmount;
706
707 switch (_pbs.HollowShape)
708 {
709 case HollowShape.Circle:
710 case HollowShape.Triangle: // diference in sl is minor and odd
711 case HollowShape.Same:
712 break;
713
714 case HollowShape.Square:
715 hollowVolume *= 0.909f;
716 break;
717
718 // case HollowShape.Triangle:
719 // hollowVolume *= .827f;
720 // break;
721 default:
722 hollowVolume = 0;
723 break;
724 }
725 volume *= (1.0f - hollowVolume);
726 }
727
728 }
729 break;
730
731 case ProfileShape.EquilateralTriangle:
732
733 if (_pbs.PathCurve == (byte)Extrusion.Straight)
734 {
735 volume *= 0.32475953f;
736
737 if (hollowAmount > 0.0)
738 {
739
740 // calculate the hollow volume by it's shape compared to the prim shape
741 switch (_pbs.HollowShape)
742 {
743 case HollowShape.Same:
744 case HollowShape.Triangle:
745 hollowVolume *= .25f;
746 break;
747
748 case HollowShape.Square:
749 hollowVolume *= 0.499849f * 3.07920140172638f;
750 break;
751
752 case HollowShape.Circle:
753 // Hollow shape is a perfect cyllinder in respect to the cube's scale
754 // Cyllinder hollow volume calculation
755
756 hollowVolume *= 0.1963495f * 3.07920140172638f;
757 break;
758
759 default:
760 hollowVolume = 0;
761 break;
762 }
763 volume *= (1.0f - hollowVolume);
764 }
765 }
766 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
767 {
768 volume *= 0.32475953f;
769 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
770 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
771 volume *= (1.0f - tmp * tmp);
772
773 if (hollowAmount > 0.0)
774 {
775
776 hollowVolume *= hollowAmount;
777
778 switch (_pbs.HollowShape)
779 {
780 case HollowShape.Same:
781 case HollowShape.Triangle:
782 hollowVolume *= .25f;
783 break;
784
785 case HollowShape.Square:
786 hollowVolume *= 0.499849f * 3.07920140172638f;
787 break;
788
789 case HollowShape.Circle:
790
791 hollowVolume *= 0.1963495f * 3.07920140172638f;
792 break;
793
794 default:
795 hollowVolume = 0;
796 break;
797 }
798 volume *= (1.0f - hollowVolume);
799 }
800 }
801 break;
802
803 default:
804 break;
805 }
806
807 float taperX1;
808 float taperY1;
809 float taperX;
810 float taperY;
811 float pathBegin;
812 float pathEnd;
813 float profileBegin;
814 float profileEnd;
815
816 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
817 {
818 taperX1 = _pbs.PathScaleX * 0.01f;
819 if (taperX1 > 1.0f)
820 taperX1 = 2.0f - taperX1;
821 taperX = 1.0f - taperX1;
822
823 taperY1 = _pbs.PathScaleY * 0.01f;
824 if (taperY1 > 1.0f)
825 taperY1 = 2.0f - taperY1;
826 taperY = 1.0f - taperY1;
827 }
828 else
829 {
830 taperX = _pbs.PathTaperX * 0.01f;
831 if (taperX < 0.0f)
832 taperX = -taperX;
833 taperX1 = 1.0f - taperX;
834
835 taperY = _pbs.PathTaperY * 0.01f;
836 if (taperY < 0.0f)
837 taperY = -taperY;
838 taperY1 = 1.0f - taperY;
839 }
840
841 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
842
843 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
844 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
845 volume *= (pathEnd - pathBegin);
846
847 // this is crude aproximation
848 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
849 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
850 volume *= (profileEnd - profileBegin);
851
852 repData.volume = volume;
853 }
854
855 private void CalcVolumeData(ODEPhysRepData repData)
856 {
857 if (repData.hasOBB)
858 {
859 Vector3 OBB = repData.OBB;
860 }
861 else
862 {
863 Vector3 OBB = repData.size;
864 OBB.X *= 0.5f;
865 OBB.Y *= 0.5f;
866 OBB.Z *= 0.5f;
867
868 repData.OBB = OBB;
869 repData.OBBOffset = Vector3.Zero;
870 }
871
872 CalculateBasicPrimVolume(repData);
873 }
874 }
875
876 public class ODEAssetRequest
877 {
878 ODEMeshWorker m_worker;
879 private ILog m_log;
880 ODEPhysRepData repData;
881
882 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
883 ODEPhysRepData pRepData, ILog plog)
884 {
885 m_worker = pWorker;
886 m_log = plog;
887 repData = pRepData;
888
889 repData.meshState = MeshState.AssetFailed;
890 if (provider == null)
891 return;
892
893 if (repData.assetID == null)
894 return;
895
896 UUID assetID = (UUID) repData.assetID;
897 if (assetID == UUID.Zero)
898 return;
899
900 repData.meshState = MeshState.loadingAsset;
901 provider(assetID, ODEassetReceived);
902 }
903
904 void ODEassetReceived(AssetBase asset)
905 {
906 repData.meshState = MeshState.AssetFailed;
907 if (asset != null)
908 {
909 if (asset.Data != null && asset.Data.Length > 0)
910 {
911 repData.meshState = MeshState.noNeed;
912
913 if (!repData.pbs.SculptEntry)
914 return;
915 if (repData.pbs.SculptTexture != repData.assetID)
916 return;
917
918// repData.pbs.SculptData = new byte[asset.Data.Length];
919// asset.Data.CopyTo(repData.pbs.SculptData,0);
920 repData.pbs.SculptData = asset.Data;
921 repData.meshState = MeshState.AssetOK;
922 m_worker.AssetLoaded(repData);
923 }
924 else
925 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
926 repData.actor.Name, asset.ID.ToString());
927 }
928 else
929 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
930 repData.actor.Name);
931 }
932 }
933}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs
new file mode 100644
index 0000000..bd66b4d
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEModule.cs
@@ -0,0 +1,97 @@
1using System;
2using System.Reflection;
3using log4net;
4using Nini.Config;
5using Mono.Addins;
6using OdeAPI;
7using OpenSim.Framework;
8using OpenSim.Region.Framework.Scenes;
9using OpenSim.Region.Framework.Interfaces;
10
11namespace OpenSim.Region.PhysicsModule.ubOde
12{
13 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ubODEPhysicsScene")]
14 class ubOdeModule : INonSharedRegionModule
15 {
16 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
17
18 private bool m_Enabled = false;
19 private IConfigSource m_config;
20 private ODEScene m_scene;
21 private bool OSOdeLib;
22
23 #region INonSharedRegionModule
24
25 public string Name
26 {
27 get { return "ubODE"; }
28 }
29
30 public Type ReplaceableInterface
31 {
32 get { return null; }
33 }
34
35 public void Initialise(IConfigSource source)
36 {
37 IConfig config = source.Configs["Startup"];
38 if (config != null)
39 {
40 string physics = config.GetString("physics", string.Empty);
41 if (physics == Name)
42 {
43 m_config = source;
44 m_Enabled = true;
45 }
46 }
47 }
48
49 public void Close()
50 {
51 }
52
53 public void AddRegion(Scene scene)
54 {
55 if (!m_Enabled)
56 return;
57
58 if (Util.IsWindows())
59 Util.LoadArchSpecificWindowsDll("ode.dll");
60
61 // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to
62 // http://opensimulator.org/mantis/view.php?id=2750).
63 d.InitODE();
64
65 string ode_config = d.GetConfiguration();
66 if (ode_config != null && ode_config != "")
67 {
68 m_log.InfoFormat("[ubODE] ode library configuration: {0}", ode_config);
69 // ubODE still not avaiable
70 if (ode_config.Contains("ODE_OPENSIM"))
71 {
72 OSOdeLib = true;
73 }
74 }
75
76 m_scene = new ODEScene(scene, m_config, Name, OSOdeLib);
77 }
78
79 public void RemoveRegion(Scene scene)
80 {
81 if (!m_Enabled || m_scene == null)
82 return;
83
84 m_scene.Dispose();
85 m_scene = null;
86 }
87
88 public void RegionLoaded(Scene scene)
89 {
90 if (!m_Enabled || m_scene == null)
91 return;
92
93 m_scene.RegionLoaded();
94 }
95 #endregion
96 }
97}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
new file mode 100644
index 0000000..1dbf164
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs
@@ -0,0 +1,3962 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/*
29 * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces
30 * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised:
31 * ODEPrim.cs contains methods dealing with Prim editing, Prim
32 * characteristics and Kinetic motion.
33 * ODEDynamics.cs contains methods dealing with Prim Physical motion
34 * (dynamics) and the associated settings. Old Linear and angular
35 * motors for dynamic motion have been replace with MoveLinear()
36 * and MoveAngular(); 'Physical' is used only to switch ODE dynamic
37 * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to
38 * switch between 'VEHICLE' parameter use and general dynamics
39 * settings use.
40 */
41
42//#define SPAM
43
44using System;
45using System.Collections.Generic;
46using System.Reflection;
47using System.Runtime.InteropServices;
48using System.Threading;
49using log4net;
50using OpenMetaverse;
51using OdeAPI;
52using OpenSim.Framework;
53using OpenSim.Region.PhysicsModules.SharedBase;
54
55namespace OpenSim.Region.PhysicsModule.ubOde
56{
57 public class OdePrim : PhysicsActor
58 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60
61 private bool m_isphysical;
62 private bool m_fakeisphysical;
63 private bool m_isphantom;
64 private bool m_fakeisphantom;
65 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
66 private bool m_fakeisVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
67
68 protected bool m_building;
69 protected bool m_forcePosOrRotation;
70 private bool m_iscolliding;
71
72 internal bool m_isSelected;
73 private bool m_delaySelect;
74 private bool m_lastdoneSelected;
75 internal bool m_outbounds;
76
77 private byte m_angularlocks = 0;
78
79 private Quaternion m_lastorientation;
80 private Quaternion _orientation;
81
82 private Vector3 _position;
83 private Vector3 _velocity;
84 private Vector3 m_torque;
85 private Vector3 m_lastVelocity;
86 private Vector3 m_lastposition;
87 private Vector3 m_rotationalVelocity;
88 private Vector3 _size;
89 private Vector3 _acceleration;
90 private IntPtr Amotor;
91
92 private Vector3 m_force;
93 private Vector3 m_forceacc;
94 private Vector3 m_angularForceacc;
95
96 private float m_invTimeStep;
97 private float m_timeStep;
98
99 private Vector3 m_PIDTarget;
100 private float m_PIDTau;
101 private bool m_usePID;
102
103 private float m_PIDHoverHeight;
104 private float m_PIDHoverTau;
105 private bool m_useHoverPID;
106 private PIDHoverType m_PIDHoverType;
107 private float m_targetHoverHeight;
108 private float m_groundHeight;
109 private float m_waterHeight;
110 private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle.
111
112 private int body_autodisable_frames;
113 public int bodydisablecontrol = 0;
114 private float m_gravmod = 1.0f;
115
116 // Default we're a Geometry
117 private CollisionCategories m_collisionCategories = (CollisionCategories.Geom);
118 // Default colide nonphysical don't try to colide with anything
119 private const CollisionCategories m_default_collisionFlagsNotPhysical = 0;
120
121 private const CollisionCategories m_default_collisionFlagsPhysical = (CollisionCategories.Geom |
122 CollisionCategories.Character |
123 CollisionCategories.Land |
124 CollisionCategories.VolumeDtc);
125
126// private bool m_collidesLand = true;
127 private bool m_collidesWater;
128// public bool m_returnCollisions;
129
130 private bool m_NoColide; // for now only for internal use for bad meshs
131
132
133 // Default, Collide with Other Geometries, spaces and Bodies
134 private CollisionCategories m_collisionFlags = m_default_collisionFlagsNotPhysical;
135
136 public bool m_disabled;
137
138 private uint m_localID;
139
140 private IMesh m_mesh;
141 private object m_meshlock = new object();
142 private PrimitiveBaseShape _pbs;
143
144 private UUID? m_assetID;
145 private MeshState m_meshState;
146
147 public ODEScene _parent_scene;
148
149 /// <summary>
150 /// The physics space which contains prim geometry
151 /// </summary>
152 public IntPtr m_targetSpace;
153
154 public IntPtr prim_geom;
155 public IntPtr _triMeshData;
156
157 private PhysicsActor _parent;
158
159 private List<OdePrim> childrenPrim = new List<OdePrim>();
160
161 public float m_collisionscore;
162 private int m_colliderfilter = 0;
163
164 public IntPtr collide_geom; // for objects: geom if single prim space it linkset
165
166 private float m_density;
167 private byte m_shapetype;
168 public bool _zeroFlag;
169 private bool m_lastUpdateSent;
170
171 public IntPtr Body;
172
173 private Vector3 _target_velocity;
174
175 public Vector3 m_OBBOffset;
176 public Vector3 m_OBB;
177 public float primOOBradiusSQ;
178
179 private bool m_hasOBB = true;
180
181 private float m_physCost;
182 private float m_streamCost;
183
184 public d.Mass primdMass; // prim inertia information on it's own referencial
185 float primMass; // prim own mass
186 float primVolume; // prim own volume;
187 float _mass; // object mass acording to case
188
189 public int givefakepos;
190 private Vector3 fakepos;
191 public int givefakeori;
192 private Quaternion fakeori;
193
194 private int m_eventsubscription;
195 private int m_cureventsubscription;
196 private CollisionEventUpdate CollisionEventsThisFrame = null;
197 private bool SentEmptyCollisionsEvent;
198
199 public volatile bool childPrim;
200
201 public ODEDynamics m_vehicle;
202
203 internal int m_material = (int)Material.Wood;
204 private float mu;
205 private float bounce;
206
207 /// <summary>
208 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
209 /// </summary>
210 public override bool IsPhysical // this is not reliable for internal use
211 {
212 get { return m_fakeisphysical; }
213 set
214 {
215 m_fakeisphysical = value; // we show imediatly to outside that we changed physical
216 // and also to stop imediatly some updates
217 // but real change will only happen in taintprocessing
218
219 if (!value) // Zero the remembered last velocity
220 m_lastVelocity = Vector3.Zero;
221 AddChange(changes.Physical, value);
222 }
223 }
224
225 public override bool IsVolumeDtc
226 {
227 get { return m_fakeisVolumeDetect; }
228 set
229 {
230 m_fakeisVolumeDetect = value;
231 AddChange(changes.VolumeDtc, value);
232 }
233 }
234
235 public override bool Phantom // this is not reliable for internal use
236 {
237 get { return m_fakeisphantom; }
238 set
239 {
240 m_fakeisphantom = value;
241 AddChange(changes.Phantom, value);
242 }
243 }
244
245 public override bool Building // this is not reliable for internal use
246 {
247 get { return m_building; }
248 set
249 {
250// if (value)
251// m_building = true;
252 AddChange(changes.building, value);
253 }
254 }
255
256 public override void getContactData(ref ContactData cdata)
257 {
258 cdata.mu = mu;
259 cdata.bounce = bounce;
260
261 // cdata.softcolide = m_softcolide;
262 cdata.softcolide = false;
263
264 if (m_isphysical)
265 {
266 ODEDynamics veh;
267 if (_parent != null)
268 veh = ((OdePrim)_parent).m_vehicle;
269 else
270 veh = m_vehicle;
271
272 if (veh != null && veh.Type != Vehicle.TYPE_NONE)
273 cdata.mu *= veh.FrictionFactor;
274// cdata.mu *= 0;
275 }
276 }
277
278 public override float PhysicsCost
279 {
280 get
281 {
282 return m_physCost;
283 }
284 }
285
286 public override float StreamCost
287 {
288 get
289 {
290 return m_streamCost;
291 }
292 }
293
294 public override int PhysicsActorType
295 {
296 get { return (int)ActorTypes.Prim; }
297 set { return; }
298 }
299
300 public override bool SetAlwaysRun
301 {
302 get { return false; }
303 set { return; }
304 }
305
306 public override uint LocalID
307 {
308 get { return m_localID; }
309 set { m_localID = value; }
310 }
311
312 public override PhysicsActor ParentActor
313 {
314 get
315 {
316 if (childPrim)
317 return _parent;
318 else
319 return (PhysicsActor)this;
320 }
321 }
322
323 public override bool Grabbed
324 {
325 set { return; }
326 }
327
328 public override bool Selected
329 {
330 set
331 {
332 if (value)
333 m_isSelected = value; // if true set imediatly to stop moves etc
334 AddChange(changes.Selected, value);
335 }
336 }
337
338 public override bool Flying
339 {
340 // no flying prims for you
341 get { return false; }
342 set { }
343 }
344
345 public override bool IsColliding
346 {
347 get { return m_iscolliding; }
348 set
349 {
350 if (value)
351 {
352 m_colliderfilter += 2;
353 if (m_colliderfilter > 2)
354 m_colliderfilter = 2;
355 }
356 else
357 {
358 m_colliderfilter--;
359 if (m_colliderfilter < 0)
360 m_colliderfilter = 0;
361 }
362
363 if (m_colliderfilter == 0)
364 m_iscolliding = false;
365 else
366 m_iscolliding = true;
367 }
368 }
369
370 public override bool CollidingGround
371 {
372 get { return false; }
373 set { return; }
374 }
375
376 public override bool CollidingObj
377 {
378 get { return false; }
379 set { return; }
380 }
381
382
383 public override bool ThrottleUpdates {get;set;}
384
385 public override bool Stopped
386 {
387 get { return _zeroFlag; }
388 }
389
390 public override Vector3 Position
391 {
392 get
393 {
394 if (givefakepos > 0)
395 return fakepos;
396 else
397 return _position;
398 }
399
400 set
401 {
402 fakepos = value;
403 givefakepos++;
404 AddChange(changes.Position, value);
405 }
406 }
407
408 public override Vector3 Size
409 {
410 get { return _size; }
411 set
412 {
413 if (value.IsFinite())
414 {
415 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype);
416 }
417 else
418 {
419 m_log.WarnFormat("[PHYSICS]: Got NaN Size on object {0}", Name);
420 }
421 }
422 }
423
424 public override float Mass
425 {
426 get { return primMass; }
427 }
428
429 public override Vector3 Force
430 {
431 get { return m_force; }
432 set
433 {
434 if (value.IsFinite())
435 {
436 AddChange(changes.Force, value);
437 }
438 else
439 {
440 m_log.WarnFormat("[PHYSICS]: NaN in Force Applied to an Object {0}", Name);
441 }
442 }
443 }
444
445 public override void SetVolumeDetect(int param)
446 {
447 m_fakeisVolumeDetect = (param != 0);
448 AddChange(changes.VolumeDtc, m_fakeisVolumeDetect);
449 }
450
451 public override Vector3 GeometricCenter
452 {
453 // this is not real geometric center but a average of positions relative to root prim acording to
454 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
455 // ignoring tortured prims details since sl also seems to ignore
456 // so no real use in doing it on physics
457 get
458 {
459 return Vector3.Zero;
460 }
461 }
462
463 public override Vector3 CenterOfMass
464 {
465 get
466 {
467 lock (_parent_scene.OdeLock)
468 {
469 d.Vector3 dtmp;
470 if (!childPrim && Body != IntPtr.Zero)
471 {
472 dtmp = d.BodyGetPosition(Body);
473 return new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
474 }
475 else if (prim_geom != IntPtr.Zero)
476 {
477 d.Quaternion dq;
478 d.GeomCopyQuaternion(prim_geom, out dq);
479 Quaternion q;
480 q.X = dq.X;
481 q.Y = dq.Y;
482 q.Z = dq.Z;
483 q.W = dq.W;
484
485 Vector3 Ptot = m_OBBOffset * q;
486 dtmp = d.GeomGetPosition(prim_geom);
487 Ptot.X += dtmp.X;
488 Ptot.Y += dtmp.Y;
489 Ptot.Z += dtmp.Z;
490
491 // if(childPrim) we only know about physical linksets
492 return Ptot;
493/*
494 float tmass = _mass;
495 Ptot *= tmass;
496
497 float m;
498
499 foreach (OdePrim prm in childrenPrim)
500 {
501 m = prm._mass;
502 Ptot += prm.CenterOfMass * m;
503 tmass += m;
504 }
505
506 if (tmass == 0)
507 tmass = 0;
508 else
509 tmass = 1.0f / tmass;
510
511 Ptot *= tmass;
512 return Ptot;
513*/
514 }
515 else
516 return _position;
517 }
518 }
519 }
520
521 public override Vector3 OOBsize
522 {
523 get
524 {
525 return m_OBB;
526 }
527 }
528
529 public override Vector3 OOBoffset
530 {
531 get
532 {
533 return m_OBBOffset;
534 }
535 }
536
537 public override float OOBRadiusSQ
538 {
539 get
540 {
541 return primOOBradiusSQ;
542 }
543 }
544
545 public override PrimitiveBaseShape Shape
546 {
547 set
548 {
549// AddChange(changes.Shape, value);
550 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype);
551 }
552 }
553
554 public override byte PhysicsShapeType
555 {
556 get
557 {
558 return m_shapetype;
559 }
560 set
561 {
562 m_shapetype = value;
563 _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value);
564 }
565 }
566
567 public override Vector3 Velocity
568 {
569 get
570 {
571 if (_zeroFlag)
572 return Vector3.Zero;
573 return _velocity;
574 }
575 set
576 {
577 if (value.IsFinite())
578 {
579 AddChange(changes.Velocity, value);
580 }
581 else
582 {
583 m_log.WarnFormat("[PHYSICS]: Got NaN Velocity in Object {0}", Name);
584 }
585
586 }
587 }
588
589 public override Vector3 Torque
590 {
591 get
592 {
593 if (!IsPhysical || Body == IntPtr.Zero)
594 return Vector3.Zero;
595
596 return m_torque;
597 }
598
599 set
600 {
601 if (value.IsFinite())
602 {
603 AddChange(changes.Torque, value);
604 }
605 else
606 {
607 m_log.WarnFormat("[PHYSICS]: Got NaN Torque in Object {0}", Name);
608 }
609 }
610 }
611
612 public override float CollisionScore
613 {
614 get { return m_collisionscore; }
615 set { m_collisionscore = value; }
616 }
617
618 public override bool Kinematic
619 {
620 get { return false; }
621 set { }
622 }
623
624 public override Quaternion Orientation
625 {
626 get
627 {
628 if (givefakeori > 0)
629 return fakeori;
630 else
631
632 return _orientation;
633 }
634 set
635 {
636 if (QuaternionIsFinite(value))
637 {
638 fakeori = value;
639 givefakeori++;
640
641 value.Normalize();
642
643 AddChange(changes.Orientation, value);
644 }
645 else
646 m_log.WarnFormat("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object {0}", Name);
647
648 }
649 }
650
651 public override Vector3 Acceleration
652 {
653 get { return _acceleration; }
654 set { }
655 }
656
657 public override Vector3 RotationalVelocity
658 {
659 get
660 {
661 Vector3 pv = Vector3.Zero;
662 if (_zeroFlag)
663 return pv;
664
665 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
666 return pv;
667
668 return m_rotationalVelocity;
669 }
670 set
671 {
672 if (value.IsFinite())
673 {
674 AddChange(changes.AngVelocity, value);
675 }
676 else
677 {
678 m_log.WarnFormat("[PHYSICS]: Got NaN RotationalVelocity in Object {0}", Name);
679 }
680 }
681 }
682
683 public override float Buoyancy
684 {
685 get { return m_buoyancy; }
686 set
687 {
688 AddChange(changes.Buoyancy,value);
689 }
690 }
691
692 public override bool FloatOnWater
693 {
694 set
695 {
696 AddChange(changes.CollidesWater, value);
697 }
698 }
699
700 public override Vector3 PIDTarget
701 {
702 set
703 {
704 if (value.IsFinite())
705 {
706 AddChange(changes.PIDTarget,value);
707 }
708 else
709 m_log.WarnFormat("[PHYSICS]: Got NaN PIDTarget from Scene on Object {0}", Name);
710 }
711 }
712
713 public override bool PIDActive
714 {
715 get
716 {
717 return m_usePID;
718 }
719 set
720 {
721 AddChange(changes.PIDActive,value);
722 }
723 }
724
725 public override float PIDTau
726 {
727 set
728 {
729 float tmp = 0;
730 if (value > 0)
731 {
732 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
733 if (value < mint)
734 tmp = mint;
735 else
736 tmp = value;
737 }
738 AddChange(changes.PIDTau,tmp);
739 }
740 }
741
742 public override float PIDHoverHeight
743 {
744 set
745 {
746 AddChange(changes.PIDHoverHeight,value);
747 }
748 }
749 public override bool PIDHoverActive
750 {
751 get
752 {
753 return m_useHoverPID;
754 }
755 set
756 {
757 AddChange(changes.PIDHoverActive, value);
758 }
759 }
760
761 public override PIDHoverType PIDHoverType
762 {
763 set
764 {
765 AddChange(changes.PIDHoverType,value);
766 }
767 }
768
769 public override float PIDHoverTau
770 {
771 set
772 {
773 float tmp =0;
774 if (value > 0)
775 {
776 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
777 if (value < mint)
778 tmp = mint;
779 else
780 tmp = value;
781 }
782 AddChange(changes.PIDHoverTau, tmp);
783 }
784 }
785
786 public override Quaternion APIDTarget { set { return; } }
787
788 public override bool APIDActive { set { return; } }
789
790 public override float APIDStrength { set { return; } }
791
792 public override float APIDDamping { set { return; } }
793
794 public override int VehicleType
795 {
796 // we may need to put a fake on this
797 get
798 {
799 if (m_vehicle == null)
800 return (int)Vehicle.TYPE_NONE;
801 else
802 return (int)m_vehicle.Type;
803 }
804 set
805 {
806 AddChange(changes.VehicleType, value);
807 }
808 }
809
810 public override void VehicleFloatParam(int param, float value)
811 {
812 strVehicleFloatParam fp = new strVehicleFloatParam();
813 fp.param = param;
814 fp.value = value;
815 AddChange(changes.VehicleFloatParam, fp);
816 }
817
818 public override void VehicleVectorParam(int param, Vector3 value)
819 {
820 strVehicleVectorParam fp = new strVehicleVectorParam();
821 fp.param = param;
822 fp.value = value;
823 AddChange(changes.VehicleVectorParam, fp);
824 }
825
826 public override void VehicleRotationParam(int param, Quaternion value)
827 {
828 strVehicleQuatParam fp = new strVehicleQuatParam();
829 fp.param = param;
830 fp.value = value;
831 AddChange(changes.VehicleRotationParam, fp);
832 }
833
834 public override void VehicleFlags(int param, bool value)
835 {
836 strVehicleBoolParam bp = new strVehicleBoolParam();
837 bp.param = param;
838 bp.value = value;
839 AddChange(changes.VehicleFlags, bp);
840 }
841
842 public override void SetVehicle(object vdata)
843 {
844 AddChange(changes.SetVehicle, vdata);
845 }
846 public void SetAcceleration(Vector3 accel)
847 {
848 _acceleration = accel;
849 }
850
851 public override void AddForce(Vector3 force, bool pushforce)
852 {
853 if (force.IsFinite())
854 {
855 if(pushforce)
856 AddChange(changes.AddForce, force);
857 else // a impulse
858 AddChange(changes.AddForce, force * m_invTimeStep);
859 }
860 else
861 {
862 m_log.WarnFormat("[PHYSICS]: Got Invalid linear force vector from Scene in Object {0}", Name);
863 }
864 //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString());
865 }
866
867 public override void AddAngularForce(Vector3 force, bool pushforce)
868 {
869 if (force.IsFinite())
870 {
871// if(pushforce) for now applyrotationimpulse seems more happy applied as a force
872 AddChange(changes.AddAngForce, force);
873// else // a impulse
874// AddChange(changes.AddAngForce, force * m_invTimeStep);
875 }
876 else
877 {
878 m_log.WarnFormat("[PHYSICS]: Got Invalid Angular force vector from Scene in Object {0}", Name);
879 }
880 }
881
882 public override void CrossingFailure()
883 {
884 if (m_outbounds)
885 {
886 _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f);
887 _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f);
888 _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f);
889
890 m_lastposition = _position;
891 _velocity.X = 0;
892 _velocity.Y = 0;
893 _velocity.Z = 0;
894
895 m_lastVelocity = _velocity;
896 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
897 m_vehicle.Stop();
898
899 if(Body != IntPtr.Zero)
900 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
901 if (prim_geom != IntPtr.Zero)
902 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
903
904 m_outbounds = false;
905 changeDisable(false);
906 base.RequestPhysicsterseUpdate();
907 }
908 }
909
910 public override void SetMomentum(Vector3 momentum)
911 {
912 }
913
914 public override void SetMaterial(int pMaterial)
915 {
916 m_material = pMaterial;
917 mu = _parent_scene.m_materialContactsData[pMaterial].mu;
918 bounce = _parent_scene.m_materialContactsData[pMaterial].bounce;
919 }
920
921 public override float Density
922 {
923 get
924 {
925 return m_density * 100f;
926 }
927 set
928 {
929 m_density = value / 100f;
930 // for not prim mass is not updated since this implies full rebuild of body inertia TODO
931 }
932 }
933 public override float GravModifier
934 {
935 get
936 {
937 return m_gravmod;
938 }
939 set
940 {
941 m_gravmod = value;
942 if (m_vehicle != null)
943 m_vehicle.GravMod = m_gravmod;
944 }
945 }
946 public override float Friction
947 {
948 get
949 {
950 return mu;
951 }
952 set
953 {
954 mu = value;
955 }
956 }
957
958 public override float Restitution
959 {
960 get
961 {
962 return bounce;
963 }
964 set
965 {
966 bounce = value;
967 }
968 }
969
970 public void setPrimForRemoval()
971 {
972 AddChange(changes.Remove, null);
973 }
974
975 public override void link(PhysicsActor obj)
976 {
977 AddChange(changes.Link, obj);
978 }
979
980 public override void delink()
981 {
982 AddChange(changes.DeLink, null);
983 }
984
985 public override void LockAngularMotion(byte axislock)
986 {
987// m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z);
988 AddChange(changes.AngLock, axislock);
989
990 }
991
992 public override void SubscribeEvents(int ms)
993 {
994 m_eventsubscription = ms;
995 m_cureventsubscription = 0;
996 if (CollisionEventsThisFrame == null)
997 CollisionEventsThisFrame = new CollisionEventUpdate();
998 SentEmptyCollisionsEvent = false;
999 }
1000
1001 public override void UnSubscribeEvents()
1002 {
1003 if (CollisionEventsThisFrame != null)
1004 {
1005 CollisionEventsThisFrame.Clear();
1006 CollisionEventsThisFrame = null;
1007 }
1008 m_eventsubscription = 0;
1009 _parent_scene.RemoveCollisionEventReporting(this);
1010 }
1011
1012 public override void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1013 {
1014 if (CollisionEventsThisFrame == null)
1015 CollisionEventsThisFrame = new CollisionEventUpdate();
1016// if(CollisionEventsThisFrame.Count < 32)
1017 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1018 }
1019
1020 public void SendCollisions()
1021 {
1022 if (CollisionEventsThisFrame == null)
1023 return;
1024
1025 if (m_cureventsubscription < m_eventsubscription)
1026 return;
1027
1028 m_cureventsubscription = 0;
1029
1030 int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count;
1031
1032 if (!SentEmptyCollisionsEvent || ncolisions > 0)
1033 {
1034 base.SendCollisionUpdate(CollisionEventsThisFrame);
1035
1036 if (ncolisions == 0)
1037 {
1038 SentEmptyCollisionsEvent = true;
1039 _parent_scene.RemoveCollisionEventReporting(this);
1040 }
1041 else
1042 {
1043 SentEmptyCollisionsEvent = false;
1044 CollisionEventsThisFrame.Clear();
1045 }
1046 }
1047 }
1048
1049 internal void AddCollisionFrameTime(int t)
1050 {
1051 if (m_cureventsubscription < 50000)
1052 m_cureventsubscription += t;
1053 }
1054
1055 public override bool SubscribedEvents()
1056 {
1057 if (m_eventsubscription > 0)
1058 return true;
1059 return false;
1060 }
1061
1062 public OdePrim(String primName, ODEScene parent_scene, Vector3 pos, Vector3 size,
1063 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical,bool pisPhantom,byte _shapeType,uint plocalID)
1064 {
1065 Name = primName;
1066 LocalID = plocalID;
1067
1068 m_vehicle = null;
1069
1070 if (!pos.IsFinite())
1071 {
1072 pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f),
1073 parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f);
1074 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Position for {0}", Name);
1075 }
1076 _position = pos;
1077 givefakepos = 0;
1078
1079 m_timeStep = parent_scene.ODE_STEPSIZE;
1080 m_invTimeStep = 1f / m_timeStep;
1081
1082 m_density = parent_scene.geomDefaultDensity;
1083 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
1084
1085 prim_geom = IntPtr.Zero;
1086 collide_geom = IntPtr.Zero;
1087 Body = IntPtr.Zero;
1088
1089 if (!size.IsFinite())
1090 {
1091 size = new Vector3(0.5f, 0.5f, 0.5f);
1092 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Size for {0}", Name);
1093 }
1094
1095 if (size.X <= 0) size.X = 0.01f;
1096 if (size.Y <= 0) size.Y = 0.01f;
1097 if (size.Z <= 0) size.Z = 0.01f;
1098
1099 _size = size;
1100
1101 if (!QuaternionIsFinite(rotation))
1102 {
1103 rotation = Quaternion.Identity;
1104 m_log.WarnFormat("[PHYSICS]: Got nonFinite Object create Rotation for {0}", Name);
1105 }
1106
1107 _orientation = rotation;
1108 givefakeori = 0;
1109
1110 _pbs = pbs;
1111
1112 _parent_scene = parent_scene;
1113 m_targetSpace = IntPtr.Zero;
1114
1115 if (pos.Z < 0)
1116 {
1117 m_isphysical = false;
1118 }
1119 else
1120 {
1121 m_isphysical = pisPhysical;
1122 }
1123 m_fakeisphysical = m_isphysical;
1124
1125 m_isVolumeDetect = false;
1126 m_fakeisVolumeDetect = false;
1127
1128 m_force = Vector3.Zero;
1129
1130 m_iscolliding = false;
1131 m_colliderfilter = 0;
1132 m_NoColide = false;
1133
1134 _triMeshData = IntPtr.Zero;
1135
1136 m_shapetype = _shapeType;
1137
1138 m_lastdoneSelected = false;
1139 m_isSelected = false;
1140 m_delaySelect = false;
1141
1142 m_isphantom = pisPhantom;
1143 m_fakeisphantom = pisPhantom;
1144
1145 mu = parent_scene.m_materialContactsData[(int)Material.Wood].mu;
1146 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
1147
1148 m_building = true; // control must set this to false when done
1149
1150 // get basic mass parameters
1151 ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, m_shapetype);
1152
1153 primVolume = repData.volume;
1154 m_OBB = repData.OBB;
1155 m_OBBOffset = repData.OBBOffset;
1156
1157 UpdatePrimBodyData();
1158 }
1159
1160 private void resetCollisionAccounting()
1161 {
1162 m_collisionscore = 0;
1163 }
1164
1165 private void UpdateCollisionCatFlags()
1166 {
1167 if(m_isphysical && m_disabled)
1168 {
1169 m_collisionCategories = 0;
1170 m_collisionFlags = 0;
1171 }
1172
1173 else if (m_isSelected)
1174 {
1175 m_collisionCategories = CollisionCategories.Selected;
1176 m_collisionFlags = 0;
1177 }
1178
1179 else if (m_isVolumeDetect)
1180 {
1181 m_collisionCategories = CollisionCategories.VolumeDtc;
1182 if (m_isphysical)
1183 m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1184 else
1185 m_collisionFlags = 0;
1186 }
1187 else if (m_isphantom)
1188 {
1189 m_collisionCategories = CollisionCategories.Phantom;
1190 if (m_isphysical)
1191 m_collisionFlags = CollisionCategories.Land;
1192 else
1193 m_collisionFlags = 0;
1194 }
1195 else
1196 {
1197 m_collisionCategories = CollisionCategories.Geom;
1198 if (m_isphysical)
1199 m_collisionFlags = m_default_collisionFlagsPhysical;
1200 else
1201 m_collisionFlags = m_default_collisionFlagsNotPhysical;
1202 }
1203 }
1204
1205 private void ApplyCollisionCatFlags()
1206 {
1207 if (prim_geom != IntPtr.Zero)
1208 {
1209 if (!childPrim && childrenPrim.Count > 0)
1210 {
1211 foreach (OdePrim prm in childrenPrim)
1212 {
1213 if (m_isphysical && m_disabled)
1214 {
1215 prm.m_collisionCategories = 0;
1216 prm.m_collisionFlags = 0;
1217 }
1218 else
1219 {
1220 // preserve some
1221 if (prm.m_isSelected)
1222 {
1223 prm.m_collisionCategories = CollisionCategories.Selected;
1224 prm.m_collisionFlags = 0;
1225 }
1226 else if (prm.m_isVolumeDetect)
1227 {
1228 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1229 if (m_isphysical)
1230 prm.m_collisionFlags = CollisionCategories.Geom | CollisionCategories.Character;
1231 else
1232 prm.m_collisionFlags = 0;
1233 }
1234 else if (prm.m_isphantom)
1235 {
1236 prm.m_collisionCategories = CollisionCategories.Phantom;
1237 if (m_isphysical)
1238 prm.m_collisionFlags = CollisionCategories.Land;
1239 else
1240 prm.m_collisionFlags = 0;
1241 }
1242 else
1243 {
1244 prm.m_collisionCategories = m_collisionCategories;
1245 prm.m_collisionFlags = m_collisionFlags;
1246 }
1247 }
1248
1249 if (prm.prim_geom != IntPtr.Zero)
1250 {
1251 if (prm.m_NoColide)
1252 {
1253 d.GeomSetCategoryBits(prm.prim_geom, 0);
1254 if (m_isphysical)
1255 d.GeomSetCollideBits(prm.prim_geom, (int)CollisionCategories.Land);
1256 else
1257 d.GeomSetCollideBits(prm.prim_geom, 0);
1258 }
1259 else
1260 {
1261 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1262 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1263 }
1264 }
1265 }
1266 }
1267
1268 if (m_NoColide)
1269 {
1270 d.GeomSetCategoryBits(prim_geom, 0);
1271 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1272 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1273 {
1274 d.GeomSetCategoryBits(collide_geom, 0);
1275 d.GeomSetCollideBits(collide_geom, (uint)CollisionCategories.Land);
1276 }
1277 }
1278 else
1279 {
1280 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1281 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1282 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
1283 {
1284 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
1285 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
1286 }
1287 }
1288 }
1289 }
1290
1291 private void createAMotor(byte axislock)
1292 {
1293 if (Body == IntPtr.Zero)
1294 return;
1295
1296 if (Amotor != IntPtr.Zero)
1297 {
1298 d.JointDestroy(Amotor);
1299 Amotor = IntPtr.Zero;
1300 }
1301
1302 int axisnum = 0;
1303 bool axisX = false;
1304 bool axisY = false;
1305 bool axisZ = false;
1306 if((axislock & 0x02) != 0)
1307 {
1308 axisnum++;
1309 axisX = true;
1310 }
1311 if((axislock & 0x04) != 0)
1312 {
1313 axisnum++;
1314 axisY = true;
1315 }
1316 if((axislock & 0x08) != 0)
1317 {
1318 axisnum++;
1319 axisZ = true;
1320 }
1321
1322 if(axisnum == 0)
1323 return;
1324 // stop it
1325 d.BodySetTorque(Body, 0, 0, 0);
1326 d.BodySetAngularVel(Body, 0, 0, 0);
1327
1328 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1329 d.JointAttach(Amotor, Body, IntPtr.Zero);
1330
1331 d.JointSetAMotorMode(Amotor, 0);
1332
1333 d.JointSetAMotorNumAxes(Amotor, axisnum);
1334
1335 // get current orientation to lock
1336
1337 d.Quaternion dcur = d.BodyGetQuaternion(Body);
1338 Quaternion curr; // crap convertion between identical things
1339 curr.X = dcur.X;
1340 curr.Y = dcur.Y;
1341 curr.Z = dcur.Z;
1342 curr.W = dcur.W;
1343 Vector3 ax;
1344
1345 int i = 0;
1346 int j = 0;
1347 if (axisX)
1348 {
1349 ax = (new Vector3(1, 0, 0)) * curr; // rotate world X to current local X
1350 d.JointSetAMotorAxis(Amotor, 0, 0, ax.X, ax.Y, ax.Z);
1351 d.JointSetAMotorAngle(Amotor, 0, 0);
1352 d.JointSetAMotorParam(Amotor, (int)d.JointParam.LoStop, 0f);
1353 d.JointSetAMotorParam(Amotor, (int)d.JointParam.HiStop, 0f);
1354 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Vel, 0);
1355 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FudgeFactor, 0.0001f);
1356 d.JointSetAMotorParam(Amotor, (int)d.JointParam.Bounce, 0f);
1357 d.JointSetAMotorParam(Amotor, (int)d.JointParam.CFM, 0f);
1358 d.JointSetAMotorParam(Amotor, (int)d.JointParam.FMax, 5e8f);
1359 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopCFM, 0f);
1360 d.JointSetAMotorParam(Amotor, (int)d.JointParam.StopERP, 0.8f);
1361 i++;
1362 j = 256; // move to next axis set
1363 }
1364
1365 if (axisY)
1366 {
1367 ax = (new Vector3(0, 1, 0)) * curr;
1368 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1369 d.JointSetAMotorAngle(Amotor, i, 0);
1370 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
1371 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
1372 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1373 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1374 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1375 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
1376 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1377 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1378 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1379 i++;
1380 j += 256;
1381 }
1382
1383 if (axisZ)
1384 {
1385 ax = (new Vector3(0, 0, 1)) * curr;
1386 d.JointSetAMotorAxis(Amotor, i, 0, ax.X, ax.Y, ax.Z);
1387 d.JointSetAMotorAngle(Amotor, i, 0);
1388 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.LoStop, 0f);
1389 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.HiStop, 0f);
1390 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Vel, 0);
1391 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FudgeFactor, 0.0001f);
1392 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.Bounce, 0f);
1393 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.CFM, 0f);
1394 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.FMax, 5e8f);
1395 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopCFM, 0f);
1396 d.JointSetAMotorParam(Amotor, j + (int)d.JointParam.StopERP, 0.8f);
1397 }
1398 }
1399
1400
1401 private void SetGeom(IntPtr geom)
1402 {
1403 prim_geom = geom;
1404 //Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
1405 if (prim_geom != IntPtr.Zero)
1406 {
1407
1408 if (m_NoColide)
1409 {
1410 d.GeomSetCategoryBits(prim_geom, 0);
1411 if (m_isphysical)
1412 {
1413 d.GeomSetCollideBits(prim_geom, (uint)CollisionCategories.Land);
1414 }
1415 else
1416 {
1417 d.GeomSetCollideBits(prim_geom, 0);
1418 d.GeomDisable(prim_geom);
1419 }
1420 }
1421 else
1422 {
1423 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1424 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1425 }
1426
1427 UpdatePrimBodyData();
1428 _parent_scene.actor_name_map[prim_geom] = this;
1429
1430/*
1431// debug
1432 d.AABB aabb;
1433 d.GeomGetAABB(prim_geom, out aabb);
1434 float x = aabb.MaxX - aabb.MinX;
1435 float y = aabb.MaxY - aabb.MinY;
1436 float z = aabb.MaxZ - aabb.MinZ;
1437 if( x > 60.0f || y > 60.0f || z > 60.0f)
1438 m_log.WarnFormat("[PHYSICS]: large prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1439 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1440 else if (x < 0.001f || y < 0.001f || z < 0.001f)
1441 m_log.WarnFormat("[PHYSICS]: small prim geo {0},size {1}, AABBsize <{2},{3},{4}, mesh {5} at {6}",
1442 Name, _size.ToString(), x, y, z, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh", _position.ToString());
1443*/
1444
1445 }
1446 else
1447 m_log.Warn("Setting bad Geom");
1448 }
1449
1450 private bool GetMeshGeom()
1451 {
1452 IntPtr vertices, indices;
1453 int vertexCount, indexCount;
1454 int vertexStride, triStride;
1455
1456 IMesh mesh = m_mesh;
1457
1458 if (mesh == null)
1459 return false;
1460
1461 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
1462 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
1463
1464 if (vertexCount == 0 || indexCount == 0)
1465 {
1466 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on OdePrim {0}, mesh {1} at {2}",
1467 Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh",_position.ToString());
1468
1469 m_hasOBB = false;
1470 m_OBBOffset = Vector3.Zero;
1471 m_OBB = _size * 0.5f;
1472
1473 m_physCost = 0.1f;
1474 m_streamCost = 1.0f;
1475
1476 _parent_scene.mesher.ReleaseMesh(mesh);
1477 m_meshState = MeshState.MeshFailed;
1478 m_mesh = null;
1479 return false;
1480 }
1481
1482 if (vertexCount > 64000 || indexCount > 64000)
1483 {
1484 m_log.WarnFormat("[PHYSICS]: large mesh data on OdePrim {0}, mesh {1} at {2}, {3} vertices, {4} indexes",
1485 Name, _pbs.SculptEntry ? _pbs.SculptTexture.ToString() : "primMesh",
1486 _position.ToString() ,vertexCount , indexCount );
1487 }
1488 IntPtr geo = IntPtr.Zero;
1489
1490 try
1491 {
1492 _triMeshData = d.GeomTriMeshDataCreate();
1493
1494 d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
1495 d.GeomTriMeshDataPreprocess(_triMeshData);
1496
1497 geo = d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null);
1498 }
1499
1500 catch (Exception e)
1501 {
1502 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", Name, e);
1503 if (_triMeshData != IntPtr.Zero)
1504 {
1505 try
1506 {
1507 d.GeomTriMeshDataDestroy(_triMeshData);
1508 }
1509 catch
1510 {
1511 }
1512 }
1513 _triMeshData = IntPtr.Zero;
1514
1515 m_hasOBB = false;
1516 m_OBBOffset = Vector3.Zero;
1517 m_OBB = _size * 0.5f;
1518 m_physCost = 0.1f;
1519 m_streamCost = 1.0f;
1520
1521 _parent_scene.mesher.ReleaseMesh(mesh);
1522 m_meshState = MeshState.MeshFailed;
1523 m_mesh = null;
1524 return false;
1525 }
1526
1527 m_physCost = 0.0013f * (float)indexCount;
1528 // todo
1529 m_streamCost = 1.0f;
1530
1531 SetGeom(geo);
1532
1533 return true;
1534 }
1535
1536 private void CreateGeom()
1537 {
1538 bool hasMesh = false;
1539
1540 m_NoColide = false;
1541
1542 if ((m_meshState & MeshState.MeshNoColide) != 0)
1543 m_NoColide = true;
1544
1545 else if(m_mesh != null)
1546 {
1547 if (GetMeshGeom())
1548 hasMesh = true;
1549 else
1550 m_NoColide = true;
1551 }
1552
1553
1554 if (!hasMesh)
1555 {
1556 IntPtr geo = IntPtr.Zero;
1557
1558 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1
1559 && _size.X == _size.Y && _size.Y == _size.Z)
1560 { // it's a sphere
1561 try
1562 {
1563 geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f);
1564 }
1565 catch (Exception e)
1566 {
1567 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
1568 return;
1569 }
1570 }
1571 else
1572 {// do it as a box
1573 try
1574 {
1575 geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z);
1576 }
1577 catch (Exception e)
1578 {
1579 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
1580 return;
1581 }
1582 }
1583 m_physCost = 0.1f;
1584 m_streamCost = 1.0f;
1585 SetGeom(geo);
1586 }
1587 }
1588
1589 private void RemoveGeom()
1590 {
1591 if (prim_geom != IntPtr.Zero)
1592 {
1593 _parent_scene.actor_name_map.Remove(prim_geom);
1594
1595 try
1596 {
1597 d.GeomDestroy(prim_geom);
1598 if (_triMeshData != IntPtr.Zero)
1599 {
1600 d.GeomTriMeshDataDestroy(_triMeshData);
1601 _triMeshData = IntPtr.Zero;
1602 }
1603 }
1604 catch (Exception e)
1605 {
1606 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction failed for {0} exception {1}", Name, e);
1607 }
1608
1609 prim_geom = IntPtr.Zero;
1610 collide_geom = IntPtr.Zero;
1611 m_targetSpace = IntPtr.Zero;
1612 }
1613 else
1614 {
1615 m_log.ErrorFormat("[PHYSICS]: PrimGeom destruction BAD {0}", Name);
1616 }
1617
1618 lock (m_meshlock)
1619 {
1620 if (m_mesh != null)
1621 {
1622 _parent_scene.mesher.ReleaseMesh(m_mesh);
1623 m_mesh = null;
1624 }
1625 }
1626
1627 Body = IntPtr.Zero;
1628 m_hasOBB = false;
1629 }
1630
1631 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1632 // should only be called for non physical prims unless they are becoming non physical
1633 private void SetInStaticSpace(OdePrim prim)
1634 {
1635 IntPtr targetSpace = _parent_scene.MoveGeomToStaticSpace(prim.prim_geom, prim._position, prim.m_targetSpace);
1636 prim.m_targetSpace = targetSpace;
1637 collide_geom = IntPtr.Zero;
1638 }
1639
1640 public void enableBodySoft()
1641 {
1642 m_disabled = false;
1643 if (!childPrim && !m_isSelected)
1644 {
1645 if (m_isphysical && Body != IntPtr.Zero)
1646 {
1647 UpdateCollisionCatFlags();
1648 ApplyCollisionCatFlags();
1649
1650 _zeroFlag = true;
1651 d.BodyEnable(Body);
1652
1653 }
1654 }
1655 resetCollisionAccounting();
1656 }
1657
1658 private void disableBodySoft()
1659 {
1660 m_disabled = true;
1661 if (!childPrim)
1662 {
1663 if (m_isphysical && Body != IntPtr.Zero)
1664 {
1665 if (m_isSelected)
1666 m_collisionFlags = CollisionCategories.Selected;
1667 else
1668 m_collisionCategories = 0;
1669 m_collisionFlags = 0;
1670 ApplyCollisionCatFlags();
1671 d.BodyDisable(Body);
1672 }
1673 }
1674 }
1675
1676 private void MakeBody()
1677 {
1678 if (!m_isphysical) // only physical get bodies
1679 return;
1680
1681 if (childPrim) // child prims don't get bodies;
1682 return;
1683
1684 if (m_building)
1685 return;
1686
1687 if (prim_geom == IntPtr.Zero)
1688 {
1689 m_log.Warn("[PHYSICS]: Unable to link the linkset. Root has no geom yet");
1690 return;
1691 }
1692
1693 if (Body != IntPtr.Zero)
1694 {
1695 DestroyBody();
1696 m_log.Warn("[PHYSICS]: MakeBody called having a body");
1697 }
1698
1699 if (d.GeomGetBody(prim_geom) != IntPtr.Zero)
1700 {
1701 d.GeomSetBody(prim_geom, IntPtr.Zero);
1702 m_log.Warn("[PHYSICS]: MakeBody root geom already had a body");
1703 }
1704
1705 d.Matrix3 mymat = new d.Matrix3();
1706 d.Quaternion myrot = new d.Quaternion();
1707 d.Mass objdmass = new d.Mass { };
1708
1709 Body = d.BodyCreate(_parent_scene.world);
1710
1711 objdmass = primdMass;
1712
1713 // rotate inertia
1714 myrot.X = _orientation.X;
1715 myrot.Y = _orientation.Y;
1716 myrot.Z = _orientation.Z;
1717 myrot.W = _orientation.W;
1718
1719 d.RfromQ(out mymat, ref myrot);
1720 d.MassRotate(ref objdmass, ref mymat);
1721
1722 // set the body rotation
1723 d.BodySetRotation(Body, ref mymat);
1724
1725 // recompute full object inertia if needed
1726 if (childrenPrim.Count > 0)
1727 {
1728 d.Matrix3 mat = new d.Matrix3();
1729 d.Quaternion quat = new d.Quaternion();
1730 d.Mass tmpdmass = new d.Mass { };
1731 Vector3 rcm;
1732
1733 rcm.X = _position.X;
1734 rcm.Y = _position.Y;
1735 rcm.Z = _position.Z;
1736
1737 lock (childrenPrim)
1738 {
1739 foreach (OdePrim prm in childrenPrim)
1740 {
1741 if (prm.prim_geom == IntPtr.Zero)
1742 {
1743 m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements, skipping it. No geom yet");
1744 continue;
1745 }
1746
1747 tmpdmass = prm.primdMass;
1748
1749 // apply prim current rotation to inertia
1750 quat.X = prm._orientation.X;
1751 quat.Y = prm._orientation.Y;
1752 quat.Z = prm._orientation.Z;
1753 quat.W = prm._orientation.W;
1754 d.RfromQ(out mat, ref quat);
1755 d.MassRotate(ref tmpdmass, ref mat);
1756
1757 Vector3 ppos = prm._position;
1758 ppos.X -= rcm.X;
1759 ppos.Y -= rcm.Y;
1760 ppos.Z -= rcm.Z;
1761 // refer inertia to root prim center of mass position
1762 d.MassTranslate(ref tmpdmass,
1763 ppos.X,
1764 ppos.Y,
1765 ppos.Z);
1766
1767 d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia
1768 // fix prim colision cats
1769
1770 if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero)
1771 {
1772 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
1773 m_log.Warn("[PHYSICS]: MakeBody child geom already had a body");
1774 }
1775
1776 d.GeomClearOffset(prm.prim_geom);
1777 d.GeomSetBody(prm.prim_geom, Body);
1778 prm.Body = Body;
1779 d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation
1780 }
1781 }
1782 }
1783
1784 d.GeomClearOffset(prim_geom); // make sure we don't have a hidden offset
1785 // associate root geom with body
1786 d.GeomSetBody(prim_geom, Body);
1787
1788 d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z);
1789 d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z);
1790
1791 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
1792 myrot.X = -myrot.X;
1793 myrot.Y = -myrot.Y;
1794 myrot.Z = -myrot.Z;
1795
1796 d.RfromQ(out mymat, ref myrot);
1797 d.MassRotate(ref objdmass, ref mymat);
1798
1799 d.BodySetMass(Body, ref objdmass);
1800 _mass = objdmass.mass;
1801
1802 // disconnect from world gravity so we can apply buoyancy
1803 d.BodySetGravityMode(Body, false);
1804
1805 d.BodySetAutoDisableFlag(Body, true);
1806 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1807 d.BodySetAutoDisableAngularThreshold(Body, 0.05f);
1808 d.BodySetAutoDisableLinearThreshold(Body, 0.05f);
1809 d.BodySetDamping(Body, .004f, .001f);
1810
1811 if (m_targetSpace != IntPtr.Zero)
1812 {
1813 _parent_scene.waitForSpaceUnlock(m_targetSpace);
1814 if (d.SpaceQuery(m_targetSpace, prim_geom))
1815 d.SpaceRemove(m_targetSpace, prim_geom);
1816 }
1817
1818 if (childrenPrim.Count == 0)
1819 {
1820 collide_geom = prim_geom;
1821 m_targetSpace = _parent_scene.ActiveSpace;
1822 }
1823 else
1824 {
1825 m_targetSpace = d.HashSpaceCreate(_parent_scene.ActiveSpace);
1826 d.HashSpaceSetLevels(m_targetSpace, -2, 8);
1827 d.SpaceSetSublevel(m_targetSpace, 3);
1828 d.SpaceSetCleanup(m_targetSpace, false);
1829
1830 d.GeomSetCategoryBits(m_targetSpace, (uint)(CollisionCategories.Space |
1831 CollisionCategories.Geom |
1832 CollisionCategories.Phantom |
1833 CollisionCategories.VolumeDtc
1834 ));
1835 d.GeomSetCollideBits(m_targetSpace, 0);
1836 collide_geom = m_targetSpace;
1837 }
1838
1839 d.SpaceAdd(m_targetSpace, prim_geom);
1840
1841 if (m_delaySelect)
1842 {
1843 m_isSelected = true;
1844 m_delaySelect = false;
1845 }
1846
1847 m_collisionscore = 0;
1848
1849 UpdateCollisionCatFlags();
1850 ApplyCollisionCatFlags();
1851
1852 _parent_scene.addActivePrim(this);
1853
1854 lock (childrenPrim)
1855 {
1856 foreach (OdePrim prm in childrenPrim)
1857 {
1858 if (prm.prim_geom == IntPtr.Zero)
1859 continue;
1860
1861 Vector3 ppos = prm._position;
1862 d.GeomSetOffsetWorldPosition(prm.prim_geom, ppos.X, ppos.Y, ppos.Z); // set relative position
1863
1864 if (prm.m_targetSpace != m_targetSpace)
1865 {
1866 if (prm.m_targetSpace != IntPtr.Zero)
1867 {
1868 _parent_scene.waitForSpaceUnlock(prm.m_targetSpace);
1869 if (d.SpaceQuery(prm.m_targetSpace, prm.prim_geom))
1870 d.SpaceRemove(prm.m_targetSpace, prm.prim_geom);
1871 }
1872 prm.m_targetSpace = m_targetSpace;
1873 d.SpaceAdd(m_targetSpace, prm.prim_geom);
1874 }
1875
1876 prm.m_collisionscore = 0;
1877
1878 if(!m_disabled)
1879 prm.m_disabled = false;
1880
1881 _parent_scene.addActivePrim(prm);
1882 }
1883 }
1884
1885 // The body doesn't already have a finite rotation mode set here
1886 if (m_angularlocks != 0 && _parent == null)
1887 {
1888 createAMotor(m_angularlocks);
1889 }
1890
1891 if (m_isSelected || m_disabled)
1892 {
1893 d.BodyDisable(Body);
1894 _zeroFlag = true;
1895 }
1896 else
1897 {
1898 d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z);
1899 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
1900 _zeroFlag = false;
1901 bodydisablecontrol = 0;
1902 }
1903 _parent_scene.addActiveGroups(this);
1904 }
1905
1906 private void DestroyBody()
1907 {
1908 if (Body != IntPtr.Zero)
1909 {
1910 _parent_scene.remActivePrim(this);
1911
1912 collide_geom = IntPtr.Zero;
1913
1914 if (m_disabled)
1915 m_collisionCategories = 0;
1916 else if (m_isSelected)
1917 m_collisionCategories = CollisionCategories.Selected;
1918 else if (m_isVolumeDetect)
1919 m_collisionCategories = CollisionCategories.VolumeDtc;
1920 else if (m_isphantom)
1921 m_collisionCategories = CollisionCategories.Phantom;
1922 else
1923 m_collisionCategories = CollisionCategories.Geom;
1924
1925 m_collisionFlags = 0;
1926
1927 if (prim_geom != IntPtr.Zero)
1928 {
1929 if (m_NoColide)
1930 {
1931 d.GeomSetCategoryBits(prim_geom, 0);
1932 d.GeomSetCollideBits(prim_geom, 0);
1933 }
1934 else
1935 {
1936 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
1937 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
1938 }
1939 UpdateDataFromGeom();
1940 d.GeomSetBody(prim_geom, IntPtr.Zero);
1941 SetInStaticSpace(this);
1942 }
1943
1944 if (!childPrim)
1945 {
1946 lock (childrenPrim)
1947 {
1948 foreach (OdePrim prm in childrenPrim)
1949 {
1950 _parent_scene.remActivePrim(prm);
1951
1952 if (prm.m_isSelected)
1953 prm.m_collisionCategories = CollisionCategories.Selected;
1954 else if (prm.m_isVolumeDetect)
1955 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1956 else if (prm.m_isphantom)
1957 prm.m_collisionCategories = CollisionCategories.Phantom;
1958 else
1959 prm.m_collisionCategories = CollisionCategories.Geom;
1960
1961 prm.m_collisionFlags = 0;
1962
1963 if (prm.prim_geom != IntPtr.Zero)
1964 {
1965 if (prm.m_NoColide)
1966 {
1967 d.GeomSetCategoryBits(prm.prim_geom, 0);
1968 d.GeomSetCollideBits(prm.prim_geom, 0);
1969 }
1970 else
1971 {
1972 d.GeomSetCategoryBits(prm.prim_geom, (uint)prm.m_collisionCategories);
1973 d.GeomSetCollideBits(prm.prim_geom, (uint)prm.m_collisionFlags);
1974 }
1975 prm.UpdateDataFromGeom();
1976 SetInStaticSpace(prm);
1977 }
1978 prm.Body = IntPtr.Zero;
1979 prm._mass = prm.primMass;
1980 prm.m_collisionscore = 0;
1981 }
1982 }
1983 if (Amotor != IntPtr.Zero)
1984 {
1985 d.JointDestroy(Amotor);
1986 Amotor = IntPtr.Zero;
1987 }
1988 _parent_scene.remActiveGroup(this);
1989 d.BodyDestroy(Body);
1990 }
1991 Body = IntPtr.Zero;
1992 }
1993 _mass = primMass;
1994 m_collisionscore = 0;
1995 }
1996
1997 private void FixInertia(Vector3 NewPos,Quaternion newrot)
1998 {
1999 d.Matrix3 mat = new d.Matrix3();
2000 d.Quaternion quat = new d.Quaternion();
2001
2002 d.Mass tmpdmass = new d.Mass { };
2003 d.Mass objdmass = new d.Mass { };
2004
2005 d.BodyGetMass(Body, out tmpdmass);
2006 objdmass = tmpdmass;
2007
2008 d.Vector3 dobjpos;
2009 d.Vector3 thispos;
2010
2011 // get current object position and rotation
2012 dobjpos = d.BodyGetPosition(Body);
2013
2014 // get prim own inertia in its local frame
2015 tmpdmass = primdMass;
2016
2017 // transform to object frame
2018 mat = d.GeomGetOffsetRotation(prim_geom);
2019 d.MassRotate(ref tmpdmass, ref mat);
2020
2021 thispos = d.GeomGetOffsetPosition(prim_geom);
2022 d.MassTranslate(ref tmpdmass,
2023 thispos.X,
2024 thispos.Y,
2025 thispos.Z);
2026
2027 // subtract current prim inertia from object
2028 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2029
2030 // back prim own inertia
2031 tmpdmass = primdMass;
2032
2033 // update to new position and orientation
2034 _position = NewPos;
2035 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2036 _orientation = newrot;
2037 quat.X = newrot.X;
2038 quat.Y = newrot.Y;
2039 quat.Z = newrot.Z;
2040 quat.W = newrot.W;
2041 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2042
2043 mat = d.GeomGetOffsetRotation(prim_geom);
2044 d.MassRotate(ref tmpdmass, ref mat);
2045
2046 thispos = d.GeomGetOffsetPosition(prim_geom);
2047 d.MassTranslate(ref tmpdmass,
2048 thispos.X,
2049 thispos.Y,
2050 thispos.Z);
2051
2052 d.MassAdd(ref objdmass, ref tmpdmass);
2053
2054 // fix all positions
2055 IntPtr g = d.BodyGetFirstGeom(Body);
2056 while (g != IntPtr.Zero)
2057 {
2058 thispos = d.GeomGetOffsetPosition(g);
2059 thispos.X -= objdmass.c.X;
2060 thispos.Y -= objdmass.c.Y;
2061 thispos.Z -= objdmass.c.Z;
2062 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2063 g = d.dBodyGetNextGeom(g);
2064 }
2065 d.BodyVectorToWorld(Body,objdmass.c.X, objdmass.c.Y, objdmass.c.Z,out thispos);
2066
2067 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2068 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2069 d.BodySetMass(Body, ref objdmass);
2070 _mass = objdmass.mass;
2071 }
2072
2073 private void FixInertia(Vector3 NewPos)
2074 {
2075 d.Matrix3 primmat = new d.Matrix3();
2076 d.Mass tmpdmass = new d.Mass { };
2077 d.Mass objdmass = new d.Mass { };
2078 d.Mass primmass = new d.Mass { };
2079
2080 d.Vector3 dobjpos;
2081 d.Vector3 thispos;
2082
2083 d.BodyGetMass(Body, out objdmass);
2084
2085 // get prim own inertia in its local frame
2086 primmass = primdMass;
2087 // transform to object frame
2088 primmat = d.GeomGetOffsetRotation(prim_geom);
2089 d.MassRotate(ref primmass, ref primmat);
2090
2091 tmpdmass = primmass;
2092
2093 thispos = d.GeomGetOffsetPosition(prim_geom);
2094 d.MassTranslate(ref tmpdmass,
2095 thispos.X,
2096 thispos.Y,
2097 thispos.Z);
2098
2099 // subtract current prim inertia from object
2100 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2101
2102 // update to new position
2103 _position = NewPos;
2104 d.GeomSetOffsetWorldPosition(prim_geom, NewPos.X, NewPos.Y, NewPos.Z);
2105
2106 thispos = d.GeomGetOffsetPosition(prim_geom);
2107 d.MassTranslate(ref primmass,
2108 thispos.X,
2109 thispos.Y,
2110 thispos.Z);
2111
2112 d.MassAdd(ref objdmass, ref primmass);
2113
2114 // fix all positions
2115 IntPtr g = d.BodyGetFirstGeom(Body);
2116 while (g != IntPtr.Zero)
2117 {
2118 thispos = d.GeomGetOffsetPosition(g);
2119 thispos.X -= objdmass.c.X;
2120 thispos.Y -= objdmass.c.Y;
2121 thispos.Z -= objdmass.c.Z;
2122 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2123 g = d.dBodyGetNextGeom(g);
2124 }
2125
2126 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2127
2128 // get current object position and rotation
2129 dobjpos = d.BodyGetPosition(Body);
2130
2131 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2132 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2133 d.BodySetMass(Body, ref objdmass);
2134 _mass = objdmass.mass;
2135 }
2136
2137 private void FixInertia(Quaternion newrot)
2138 {
2139 d.Matrix3 mat = new d.Matrix3();
2140 d.Quaternion quat = new d.Quaternion();
2141
2142 d.Mass tmpdmass = new d.Mass { };
2143 d.Mass objdmass = new d.Mass { };
2144 d.Vector3 dobjpos;
2145 d.Vector3 thispos;
2146
2147 d.BodyGetMass(Body, out objdmass);
2148
2149 // get prim own inertia in its local frame
2150 tmpdmass = primdMass;
2151 mat = d.GeomGetOffsetRotation(prim_geom);
2152 d.MassRotate(ref tmpdmass, ref mat);
2153 // transform to object frame
2154 thispos = d.GeomGetOffsetPosition(prim_geom);
2155 d.MassTranslate(ref tmpdmass,
2156 thispos.X,
2157 thispos.Y,
2158 thispos.Z);
2159
2160 // subtract current prim inertia from object
2161 DMassSubPartFromObj(ref tmpdmass, ref objdmass);
2162
2163 // update to new orientation
2164 _orientation = newrot;
2165 quat.X = newrot.X;
2166 quat.Y = newrot.Y;
2167 quat.Z = newrot.Z;
2168 quat.W = newrot.W;
2169 d.GeomSetOffsetWorldQuaternion(prim_geom, ref quat);
2170
2171 tmpdmass = primdMass;
2172 mat = d.GeomGetOffsetRotation(prim_geom);
2173 d.MassRotate(ref tmpdmass, ref mat);
2174 d.MassTranslate(ref tmpdmass,
2175 thispos.X,
2176 thispos.Y,
2177 thispos.Z);
2178
2179 d.MassAdd(ref objdmass, ref tmpdmass);
2180
2181 // fix all positions
2182 IntPtr g = d.BodyGetFirstGeom(Body);
2183 while (g != IntPtr.Zero)
2184 {
2185 thispos = d.GeomGetOffsetPosition(g);
2186 thispos.X -= objdmass.c.X;
2187 thispos.Y -= objdmass.c.Y;
2188 thispos.Z -= objdmass.c.Z;
2189 d.GeomSetOffsetPosition(g, thispos.X, thispos.Y, thispos.Z);
2190 g = d.dBodyGetNextGeom(g);
2191 }
2192
2193 d.BodyVectorToWorld(Body, objdmass.c.X, objdmass.c.Y, objdmass.c.Z, out thispos);
2194 // get current object position and rotation
2195 dobjpos = d.BodyGetPosition(Body);
2196
2197 d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z);
2198 d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body
2199 d.BodySetMass(Body, ref objdmass);
2200 _mass = objdmass.mass;
2201 }
2202
2203
2204 #region Mass Calculation
2205
2206 private void UpdatePrimBodyData()
2207 {
2208 primMass = m_density * primVolume;
2209
2210 if (primMass <= 0)
2211 primMass = 0.0001f;//ckrinke: Mass must be greater then zero.
2212 if (primMass > _parent_scene.maximumMassObject)
2213 primMass = _parent_scene.maximumMassObject;
2214
2215 _mass = primMass; // just in case
2216
2217 d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z);
2218
2219 d.MassTranslate(ref primdMass,
2220 m_OBBOffset.X,
2221 m_OBBOffset.Y,
2222 m_OBBOffset.Z);
2223
2224 primOOBradiusSQ = m_OBB.LengthSquared();
2225
2226 if (_triMeshData != IntPtr.Zero)
2227 {
2228 float pc = m_physCost;
2229 float psf = primOOBradiusSQ;
2230 psf *= 1.33f * .2f;
2231 pc *= psf;
2232 if (pc < 0.1f)
2233 pc = 0.1f;
2234
2235 m_physCost = pc;
2236 }
2237 else
2238 m_physCost = 0.1f;
2239
2240 m_streamCost = 1.0f;
2241 }
2242
2243 #endregion
2244
2245
2246 /// <summary>
2247 /// Add a child prim to this parent prim.
2248 /// </summary>
2249 /// <param name="prim">Child prim</param>
2250 // I'm the parent
2251 // prim is the child
2252 public void ParentPrim(OdePrim prim)
2253 {
2254 //Console.WriteLine("ParentPrim " + m_primName);
2255 if (this.m_localID != prim.m_localID)
2256 {
2257 DestroyBody(); // for now we need to rebuil entire object on link change
2258
2259 lock (childrenPrim)
2260 {
2261 // adopt the prim
2262 if (!childrenPrim.Contains(prim))
2263 childrenPrim.Add(prim);
2264
2265 // see if this prim has kids and adopt them also
2266 // should not happen for now
2267 foreach (OdePrim prm in prim.childrenPrim)
2268 {
2269 if (!childrenPrim.Contains(prm))
2270 {
2271 if (prm.Body != IntPtr.Zero)
2272 {
2273 if (prm.prim_geom != IntPtr.Zero)
2274 d.GeomSetBody(prm.prim_geom, IntPtr.Zero);
2275 if (prm.Body != prim.Body)
2276 prm.DestroyBody(); // don't loose bodies around
2277 prm.Body = IntPtr.Zero;
2278 }
2279
2280 childrenPrim.Add(prm);
2281 prm._parent = this;
2282 }
2283 }
2284 }
2285 //Remove old children from the prim
2286 prim.childrenPrim.Clear();
2287
2288 if (prim.Body != IntPtr.Zero)
2289 {
2290 if (prim.prim_geom != IntPtr.Zero)
2291 d.GeomSetBody(prim.prim_geom, IntPtr.Zero);
2292 prim.DestroyBody(); // don't loose bodies around
2293 prim.Body = IntPtr.Zero;
2294 }
2295
2296 prim.childPrim = true;
2297 prim._parent = this;
2298
2299 MakeBody(); // full nasty reconstruction
2300 }
2301 }
2302
2303 private void UpdateChildsfromgeom()
2304 {
2305 if (childrenPrim.Count > 0)
2306 {
2307 foreach (OdePrim prm in childrenPrim)
2308 prm.UpdateDataFromGeom();
2309 }
2310 }
2311
2312 private void UpdateDataFromGeom()
2313 {
2314 if (prim_geom != IntPtr.Zero)
2315 {
2316 d.Quaternion qtmp;
2317 d.GeomCopyQuaternion(prim_geom, out qtmp);
2318 _orientation.X = qtmp.X;
2319 _orientation.Y = qtmp.Y;
2320 _orientation.Z = qtmp.Z;
2321 _orientation.W = qtmp.W;
2322/*
2323// Debug
2324 float qlen = _orientation.Length();
2325 if (qlen > 1.01f || qlen < 0.99)
2326 m_log.WarnFormat("[PHYSICS]: Got nonnorm quaternion from geom in Object {0} norm {1}", Name, qlen);
2327//
2328*/
2329 _orientation.Normalize();
2330
2331 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
2332 _position.X = lpos.X;
2333 _position.Y = lpos.Y;
2334 _position.Z = lpos.Z;
2335 }
2336 }
2337
2338 private void ChildDelink(OdePrim odePrim, bool remakebodies)
2339 {
2340 // Okay, we have a delinked child.. destroy all body and remake
2341 if (odePrim != this && !childrenPrim.Contains(odePrim))
2342 return;
2343
2344 DestroyBody();
2345
2346 if (odePrim == this) // delinking the root prim
2347 {
2348 OdePrim newroot = null;
2349 lock (childrenPrim)
2350 {
2351 if (childrenPrim.Count > 0)
2352 {
2353 newroot = childrenPrim[0];
2354 childrenPrim.RemoveAt(0);
2355 foreach (OdePrim prm in childrenPrim)
2356 {
2357 newroot.childrenPrim.Add(prm);
2358 }
2359 childrenPrim.Clear();
2360 }
2361 if (newroot != null)
2362 {
2363 newroot.childPrim = false;
2364 newroot._parent = null;
2365 if (remakebodies)
2366 newroot.MakeBody();
2367 }
2368 }
2369 }
2370
2371 else
2372 {
2373 lock (childrenPrim)
2374 {
2375 childrenPrim.Remove(odePrim);
2376 odePrim.childPrim = false;
2377 odePrim._parent = null;
2378 // odePrim.UpdateDataFromGeom();
2379 if (remakebodies)
2380 odePrim.MakeBody();
2381 }
2382 }
2383 if (remakebodies)
2384 MakeBody();
2385 }
2386
2387 protected void ChildRemove(OdePrim odePrim, bool reMakeBody)
2388 {
2389 // Okay, we have a delinked child.. destroy all body and remake
2390 if (odePrim != this && !childrenPrim.Contains(odePrim))
2391 return;
2392
2393 DestroyBody();
2394
2395 if (odePrim == this)
2396 {
2397 OdePrim newroot = null;
2398 lock (childrenPrim)
2399 {
2400 if (childrenPrim.Count > 0)
2401 {
2402 newroot = childrenPrim[0];
2403 childrenPrim.RemoveAt(0);
2404 foreach (OdePrim prm in childrenPrim)
2405 {
2406 newroot.childrenPrim.Add(prm);
2407 }
2408 childrenPrim.Clear();
2409 }
2410 if (newroot != null)
2411 {
2412 newroot.childPrim = false;
2413 newroot._parent = null;
2414 newroot.MakeBody();
2415 }
2416 }
2417 if (reMakeBody)
2418 MakeBody();
2419 return;
2420 }
2421 else
2422 {
2423 lock (childrenPrim)
2424 {
2425 childrenPrim.Remove(odePrim);
2426 odePrim.childPrim = false;
2427 odePrim._parent = null;
2428 if (reMakeBody)
2429 odePrim.MakeBody();
2430 }
2431 }
2432 MakeBody();
2433 }
2434
2435
2436 #region changes
2437
2438 private void changeadd()
2439 {
2440 }
2441
2442 private void changeAngularLock(byte newLocks)
2443 {
2444 // do we have a Physical object?
2445 if (Body != IntPtr.Zero)
2446 {
2447 //Check that we have a Parent
2448 //If we have a parent then we're not authorative here
2449 if (_parent == null)
2450 {
2451 if (newLocks != 0)
2452 {
2453 createAMotor(newLocks);
2454 }
2455 else
2456 {
2457 if (Amotor != IntPtr.Zero)
2458 {
2459 d.JointDestroy(Amotor);
2460 Amotor = IntPtr.Zero;
2461 }
2462 }
2463 }
2464 }
2465 // Store this for later in case we get turned into a separate body
2466 m_angularlocks = newLocks;
2467 }
2468
2469 private void changeLink(OdePrim NewParent)
2470 {
2471 if (_parent == null && NewParent != null)
2472 {
2473 NewParent.ParentPrim(this);
2474 }
2475 else if (_parent != null)
2476 {
2477 if (_parent is OdePrim)
2478 {
2479 if (NewParent != _parent)
2480 {
2481 (_parent as OdePrim).ChildDelink(this, false); // for now...
2482 childPrim = false;
2483
2484 if (NewParent != null)
2485 {
2486 NewParent.ParentPrim(this);
2487 }
2488 }
2489 }
2490 }
2491 _parent = NewParent;
2492 }
2493
2494
2495 private void Stop()
2496 {
2497 if (!childPrim)
2498 {
2499// m_force = Vector3.Zero;
2500 m_forceacc = Vector3.Zero;
2501 m_angularForceacc = Vector3.Zero;
2502// m_torque = Vector3.Zero;
2503 _velocity = Vector3.Zero;
2504 _acceleration = Vector3.Zero;
2505 m_rotationalVelocity = Vector3.Zero;
2506 _target_velocity = Vector3.Zero;
2507 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
2508 m_vehicle.Stop();
2509
2510 _zeroFlag = false;
2511 base.RequestPhysicsterseUpdate();
2512 }
2513
2514 if (Body != IntPtr.Zero)
2515 {
2516 d.BodySetForce(Body, 0f, 0f, 0f);
2517 d.BodySetTorque(Body, 0f, 0f, 0f);
2518 d.BodySetLinearVel(Body, 0f, 0f, 0f);
2519 d.BodySetAngularVel(Body, 0f, 0f, 0f);
2520 }
2521 }
2522
2523 private void changePhantomStatus(bool newval)
2524 {
2525 m_isphantom = newval;
2526
2527 UpdateCollisionCatFlags();
2528 ApplyCollisionCatFlags();
2529 }
2530
2531/* not in use
2532 internal void ChildSelectedChange(bool childSelect)
2533 {
2534 if(childPrim)
2535 return;
2536
2537 if (childSelect == m_isSelected)
2538 return;
2539
2540 if (childSelect)
2541 {
2542 DoSelectedStatus(true);
2543 }
2544
2545 else
2546 {
2547 foreach (OdePrim prm in childrenPrim)
2548 {
2549 if (prm.m_isSelected)
2550 return;
2551 }
2552 DoSelectedStatus(false);
2553 }
2554 }
2555*/
2556 private void changeSelectedStatus(bool newval)
2557 {
2558 if (m_lastdoneSelected == newval)
2559 return;
2560
2561 m_lastdoneSelected = newval;
2562 DoSelectedStatus(newval);
2563 }
2564
2565 private void CheckDelaySelect()
2566 {
2567 if (m_delaySelect)
2568 {
2569 DoSelectedStatus(m_isSelected);
2570 }
2571 }
2572
2573 private void DoSelectedStatus(bool newval)
2574 {
2575 m_isSelected = newval;
2576 Stop();
2577
2578 if (newval)
2579 {
2580 if (!childPrim && Body != IntPtr.Zero)
2581 d.BodyDisable(Body);
2582
2583 if (m_delaySelect || m_isphysical)
2584 {
2585 m_collisionCategories = CollisionCategories.Selected;
2586 m_collisionFlags = 0;
2587
2588 if (!childPrim)
2589 {
2590 foreach (OdePrim prm in childrenPrim)
2591 {
2592 prm.m_collisionCategories = m_collisionCategories;
2593 prm.m_collisionFlags = m_collisionFlags;
2594
2595 if (prm.prim_geom != IntPtr.Zero)
2596 {
2597
2598 if (prm.m_NoColide)
2599 {
2600 d.GeomSetCategoryBits(prm.prim_geom, 0);
2601 d.GeomSetCollideBits(prm.prim_geom, 0);
2602 }
2603 else
2604 {
2605 d.GeomSetCategoryBits(prm.prim_geom, (uint)m_collisionCategories);
2606 d.GeomSetCollideBits(prm.prim_geom, (uint)m_collisionFlags);
2607 }
2608 }
2609 prm.m_delaySelect = false;
2610 }
2611 }
2612// else if (_parent != null)
2613// ((OdePrim)_parent).ChildSelectedChange(true);
2614
2615
2616 if (prim_geom != IntPtr.Zero)
2617 {
2618 if (m_NoColide)
2619 {
2620 d.GeomSetCategoryBits(prim_geom, 0);
2621 d.GeomSetCollideBits(prim_geom, 0);
2622 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2623 {
2624 d.GeomSetCategoryBits(collide_geom, 0);
2625 d.GeomSetCollideBits(collide_geom, 0);
2626 }
2627
2628 }
2629 else
2630 {
2631 d.GeomSetCategoryBits(prim_geom, (uint)m_collisionCategories);
2632 d.GeomSetCollideBits(prim_geom, (uint)m_collisionFlags);
2633 if (collide_geom != prim_geom && collide_geom != IntPtr.Zero)
2634 {
2635 d.GeomSetCategoryBits(collide_geom, (uint)m_collisionCategories);
2636 d.GeomSetCollideBits(collide_geom, (uint)m_collisionFlags);
2637 }
2638 }
2639 }
2640
2641 m_delaySelect = false;
2642 }
2643 else if(!m_isphysical)
2644 {
2645 m_delaySelect = true;
2646 }
2647 }
2648 else
2649 {
2650 if (!childPrim)
2651 {
2652 if (Body != IntPtr.Zero && !m_disabled)
2653 {
2654 _zeroFlag = true;
2655 d.BodyEnable(Body);
2656 }
2657 }
2658// else if (_parent != null)
2659// ((OdePrim)_parent).ChildSelectedChange(false);
2660
2661 UpdateCollisionCatFlags();
2662 ApplyCollisionCatFlags();
2663
2664 m_delaySelect = false;
2665 }
2666
2667 resetCollisionAccounting();
2668 }
2669
2670 private void changePosition(Vector3 newPos)
2671 {
2672 CheckDelaySelect();
2673 if (m_isphysical)
2674 {
2675 if (childPrim) // inertia is messed, must rebuild
2676 {
2677 if (m_building)
2678 {
2679 _position = newPos;
2680 }
2681
2682 else if (m_forcePosOrRotation && _position != newPos && Body != IntPtr.Zero)
2683 {
2684 FixInertia(newPos);
2685 if (!d.BodyIsEnabled(Body))
2686 {
2687 _zeroFlag = true;
2688 d.BodyEnable(Body);
2689 }
2690 }
2691 }
2692 else
2693 {
2694 if (_position != newPos)
2695 {
2696 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2697 _position = newPos;
2698 }
2699 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2700 {
2701 _zeroFlag = true;
2702 d.BodyEnable(Body);
2703 }
2704 }
2705 }
2706 else
2707 {
2708 if (prim_geom != IntPtr.Zero)
2709 {
2710 if (newPos != _position)
2711 {
2712 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2713 _position = newPos;
2714
2715 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2716 }
2717 }
2718 }
2719 givefakepos--;
2720 if (givefakepos < 0)
2721 givefakepos = 0;
2722// changeSelectedStatus();
2723 resetCollisionAccounting();
2724 }
2725
2726 private void changeOrientation(Quaternion newOri)
2727 {
2728 CheckDelaySelect();
2729 if (m_isphysical)
2730 {
2731 if (childPrim) // inertia is messed, must rebuild
2732 {
2733 if (m_building)
2734 {
2735 _orientation = newOri;
2736 }
2737/*
2738 else if (m_forcePosOrRotation && _orientation != newOri && Body != IntPtr.Zero)
2739 {
2740 FixInertia(_position, newOri);
2741 if (!d.BodyIsEnabled(Body))
2742 d.BodyEnable(Body);
2743 }
2744*/
2745 }
2746 else
2747 {
2748 if (newOri != _orientation)
2749 {
2750 d.Quaternion myrot = new d.Quaternion();
2751 myrot.X = newOri.X;
2752 myrot.Y = newOri.Y;
2753 myrot.Z = newOri.Z;
2754 myrot.W = newOri.W;
2755 d.GeomSetQuaternion(prim_geom, ref myrot);
2756 _orientation = newOri;
2757 if (Body != IntPtr.Zero && m_angularlocks != 0)
2758 createAMotor(m_angularlocks);
2759 }
2760 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2761 {
2762 _zeroFlag = true;
2763 d.BodyEnable(Body);
2764 }
2765 }
2766 }
2767 else
2768 {
2769 if (prim_geom != IntPtr.Zero)
2770 {
2771 if (newOri != _orientation)
2772 {
2773 d.Quaternion myrot = new d.Quaternion();
2774 myrot.X = newOri.X;
2775 myrot.Y = newOri.Y;
2776 myrot.Z = newOri.Z;
2777 myrot.W = newOri.W;
2778 d.GeomSetQuaternion(prim_geom, ref myrot);
2779 _orientation = newOri;
2780 }
2781 }
2782 }
2783 givefakeori--;
2784 if (givefakeori < 0)
2785 givefakeori = 0;
2786 resetCollisionAccounting();
2787 }
2788
2789 private void changePositionAndOrientation(Vector3 newPos, Quaternion newOri)
2790 {
2791 CheckDelaySelect();
2792 if (m_isphysical)
2793 {
2794 if (childPrim && m_building) // inertia is messed, must rebuild
2795 {
2796 _position = newPos;
2797 _orientation = newOri;
2798 }
2799 else
2800 {
2801 if (newOri != _orientation)
2802 {
2803 d.Quaternion myrot = new d.Quaternion();
2804 myrot.X = newOri.X;
2805 myrot.Y = newOri.Y;
2806 myrot.Z = newOri.Z;
2807 myrot.W = newOri.W;
2808 d.GeomSetQuaternion(prim_geom, ref myrot);
2809 _orientation = newOri;
2810 if (Body != IntPtr.Zero && m_angularlocks != 0)
2811 createAMotor(m_angularlocks);
2812 }
2813 if (_position != newPos)
2814 {
2815 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2816 _position = newPos;
2817 }
2818 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
2819 {
2820 _zeroFlag = true;
2821 d.BodyEnable(Body);
2822 }
2823 }
2824 }
2825 else
2826 {
2827 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
2828 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
2829
2830 if (prim_geom != IntPtr.Zero)
2831 {
2832 if (newOri != _orientation)
2833 {
2834 d.Quaternion myrot = new d.Quaternion();
2835 myrot.X = newOri.X;
2836 myrot.Y = newOri.Y;
2837 myrot.Z = newOri.Z;
2838 myrot.W = newOri.W;
2839 d.GeomSetQuaternion(prim_geom, ref myrot);
2840 _orientation = newOri;
2841 }
2842
2843 if (newPos != _position)
2844 {
2845 d.GeomSetPosition(prim_geom, newPos.X, newPos.Y, newPos.Z);
2846 _position = newPos;
2847
2848 m_targetSpace = _parent_scene.MoveGeomToStaticSpace(prim_geom, _position, m_targetSpace);
2849 }
2850 }
2851 }
2852 givefakepos--;
2853 if (givefakepos < 0)
2854 givefakepos = 0;
2855 givefakeori--;
2856 if (givefakeori < 0)
2857 givefakeori = 0;
2858 resetCollisionAccounting();
2859 }
2860
2861 private void changeDisable(bool disable)
2862 {
2863 if (disable)
2864 {
2865 if (!m_disabled)
2866 disableBodySoft();
2867 }
2868 else
2869 {
2870 if (m_disabled)
2871 enableBodySoft();
2872 }
2873 }
2874
2875 private void changePhysicsStatus(bool NewStatus)
2876 {
2877 CheckDelaySelect();
2878
2879 m_isphysical = NewStatus;
2880
2881 if (!childPrim)
2882 {
2883 if (NewStatus)
2884 {
2885 if (Body == IntPtr.Zero)
2886 MakeBody();
2887 }
2888 else
2889 {
2890 if (Body != IntPtr.Zero)
2891 {
2892 DestroyBody();
2893 }
2894 Stop();
2895 }
2896 }
2897
2898 resetCollisionAccounting();
2899 }
2900
2901 private void changeSize(Vector3 newSize)
2902 {
2903 }
2904
2905 private void changeShape(PrimitiveBaseShape newShape)
2906 {
2907 }
2908
2909 private void changeAddPhysRep(ODEPhysRepData repData)
2910 {
2911 _size = repData.size; //??
2912 _pbs = repData.pbs;
2913 m_shapetype = repData.shapetype;
2914
2915 m_mesh = repData.mesh;
2916
2917 m_assetID = repData.assetID;
2918 m_meshState = repData.meshState;
2919
2920 m_hasOBB = repData.hasOBB;
2921 m_OBBOffset = repData.OBBOffset;
2922 m_OBB = repData.OBB;
2923
2924 primVolume = repData.volume;
2925
2926 CreateGeom();
2927
2928 if (prim_geom != IntPtr.Zero)
2929 {
2930 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2931 d.Quaternion myrot = new d.Quaternion();
2932 myrot.X = _orientation.X;
2933 myrot.Y = _orientation.Y;
2934 myrot.Z = _orientation.Z;
2935 myrot.W = _orientation.W;
2936 d.GeomSetQuaternion(prim_geom, ref myrot);
2937 }
2938
2939 if (!m_isphysical)
2940 {
2941 SetInStaticSpace(this);
2942 UpdateCollisionCatFlags();
2943 ApplyCollisionCatFlags();
2944 }
2945 else
2946 MakeBody();
2947
2948 if ((m_meshState & MeshState.NeedMask) != 0)
2949 {
2950 repData.size = _size;
2951 repData.pbs = _pbs;
2952 repData.shapetype = m_shapetype;
2953 _parent_scene.m_meshWorker.RequestMesh(repData);
2954 }
2955 }
2956
2957 private void changePhysRepData(ODEPhysRepData repData)
2958 {
2959 CheckDelaySelect();
2960
2961 OdePrim parent = (OdePrim)_parent;
2962
2963 bool chp = childPrim;
2964
2965 if (chp)
2966 {
2967 if (parent != null)
2968 {
2969 parent.DestroyBody();
2970 }
2971 }
2972 else
2973 {
2974 DestroyBody();
2975 }
2976
2977 RemoveGeom();
2978
2979 _size = repData.size;
2980 _pbs = repData.pbs;
2981 m_shapetype = repData.shapetype;
2982
2983 m_mesh = repData.mesh;
2984
2985 m_assetID = repData.assetID;
2986 m_meshState = repData.meshState;
2987
2988 m_hasOBB = repData.hasOBB;
2989 m_OBBOffset = repData.OBBOffset;
2990 m_OBB = repData.OBB;
2991
2992 primVolume = repData.volume;
2993
2994 CreateGeom();
2995
2996 if (prim_geom != IntPtr.Zero)
2997 {
2998 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2999 d.Quaternion myrot = new d.Quaternion();
3000 myrot.X = _orientation.X;
3001 myrot.Y = _orientation.Y;
3002 myrot.Z = _orientation.Z;
3003 myrot.W = _orientation.W;
3004 d.GeomSetQuaternion(prim_geom, ref myrot);
3005 }
3006
3007 if (m_isphysical)
3008 {
3009 if (chp)
3010 {
3011 if (parent != null)
3012 {
3013 parent.MakeBody();
3014 }
3015 }
3016 else
3017 MakeBody();
3018 }
3019 else
3020 {
3021 SetInStaticSpace(this);
3022 UpdateCollisionCatFlags();
3023 ApplyCollisionCatFlags();
3024 }
3025
3026 resetCollisionAccounting();
3027
3028 if ((m_meshState & MeshState.NeedMask) != 0)
3029 {
3030 repData.size = _size;
3031 repData.pbs = _pbs;
3032 repData.shapetype = m_shapetype;
3033 _parent_scene.m_meshWorker.RequestMesh(repData);
3034 }
3035 }
3036
3037 private void changeFloatOnWater(bool newval)
3038 {
3039 m_collidesWater = newval;
3040
3041 UpdateCollisionCatFlags();
3042 ApplyCollisionCatFlags();
3043 }
3044
3045 private void changeSetTorque(Vector3 newtorque)
3046 {
3047 if (!m_isSelected)
3048 {
3049 if (m_isphysical && Body != IntPtr.Zero)
3050 {
3051 if (m_disabled)
3052 enableBodySoft();
3053 else if (!d.BodyIsEnabled(Body))
3054 d.BodyEnable(Body);
3055
3056 }
3057 m_torque = newtorque;
3058 }
3059 }
3060
3061 private void changeForce(Vector3 force)
3062 {
3063 m_force = force;
3064 if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body))
3065 d.BodyEnable(Body);
3066 }
3067
3068 private void changeAddForce(Vector3 theforce)
3069 {
3070 m_forceacc += theforce;
3071 if (!m_isSelected)
3072 {
3073 lock (this)
3074 {
3075 //m_log.Info("[PHYSICS]: dequeing forcelist");
3076 if (m_isphysical && Body != IntPtr.Zero)
3077 {
3078 if (m_disabled)
3079 enableBodySoft();
3080 else if (!d.BodyIsEnabled(Body))
3081 d.BodyEnable(Body);
3082 }
3083 }
3084 m_collisionscore = 0;
3085 }
3086 }
3087
3088 // actually angular impulse
3089 private void changeAddAngularImpulse(Vector3 aimpulse)
3090 {
3091 m_angularForceacc += aimpulse * m_invTimeStep;
3092 if (!m_isSelected)
3093 {
3094 lock (this)
3095 {
3096 if (m_isphysical && Body != IntPtr.Zero)
3097 {
3098 if (m_disabled)
3099 enableBodySoft();
3100 else if (!d.BodyIsEnabled(Body))
3101 d.BodyEnable(Body);
3102 }
3103 }
3104 m_collisionscore = 0;
3105 }
3106 }
3107
3108 private void changevelocity(Vector3 newVel)
3109 {
3110 float len = newVel.LengthSquared();
3111 if (len > 100000.0f) // limit to 100m/s
3112 {
3113 len = 100.0f / (float)Math.Sqrt(len);
3114 newVel *= len;
3115 }
3116
3117 if (!m_isSelected)
3118 {
3119 if (Body != IntPtr.Zero)
3120 {
3121 if (m_disabled)
3122 enableBodySoft();
3123 else if (!d.BodyIsEnabled(Body))
3124 d.BodyEnable(Body);
3125
3126 d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z);
3127 }
3128 //resetCollisionAccounting();
3129 }
3130 _velocity = newVel;
3131 }
3132
3133 private void changeangvelocity(Vector3 newAngVel)
3134 {
3135 float len = newAngVel.LengthSquared();
3136 if (len > _parent_scene.maxAngVelocitySQ)
3137 {
3138 len = _parent_scene.maximumAngularVelocity / (float)Math.Sqrt(len);
3139 newAngVel *= len;
3140 }
3141
3142 if (!m_isSelected)
3143 {
3144 if (Body != IntPtr.Zero)
3145 {
3146 if (m_disabled)
3147 enableBodySoft();
3148 else if (!d.BodyIsEnabled(Body))
3149 d.BodyEnable(Body);
3150
3151
3152 d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z);
3153 }
3154 //resetCollisionAccounting();
3155 }
3156 m_rotationalVelocity = newAngVel;
3157 }
3158
3159 private void changeVolumedetetion(bool newVolDtc)
3160 {
3161 m_isVolumeDetect = newVolDtc;
3162 m_fakeisVolumeDetect = newVolDtc;
3163 UpdateCollisionCatFlags();
3164 ApplyCollisionCatFlags();
3165 }
3166
3167 protected void changeBuilding(bool newbuilding)
3168 {
3169 // Check if we need to do anything
3170 if (newbuilding == m_building)
3171 return;
3172
3173 if ((bool)newbuilding)
3174 {
3175 m_building = true;
3176 if (!childPrim)
3177 DestroyBody();
3178 }
3179 else
3180 {
3181 m_building = false;
3182 CheckDelaySelect();
3183 if (!childPrim)
3184 MakeBody();
3185 }
3186 if (!childPrim && childrenPrim.Count > 0)
3187 {
3188 foreach (OdePrim prm in childrenPrim)
3189 prm.changeBuilding(m_building); // call directly
3190 }
3191 }
3192
3193 public void changeSetVehicle(VehicleData vdata)
3194 {
3195 if (m_vehicle == null)
3196 m_vehicle = new ODEDynamics(this);
3197 m_vehicle.DoSetVehicle(vdata);
3198 }
3199
3200 private void changeVehicleType(int value)
3201 {
3202 if (value == (int)Vehicle.TYPE_NONE)
3203 {
3204 if (m_vehicle != null)
3205 m_vehicle = null;
3206 }
3207 else
3208 {
3209 if (m_vehicle == null)
3210 m_vehicle = new ODEDynamics(this);
3211
3212 m_vehicle.ProcessTypeChange((Vehicle)value);
3213 }
3214 }
3215
3216 private void changeVehicleFloatParam(strVehicleFloatParam fp)
3217 {
3218 if (m_vehicle == null)
3219 return;
3220
3221 m_vehicle.ProcessFloatVehicleParam((Vehicle)fp.param, fp.value);
3222 }
3223
3224 private void changeVehicleVectorParam(strVehicleVectorParam vp)
3225 {
3226 if (m_vehicle == null)
3227 return;
3228 m_vehicle.ProcessVectorVehicleParam((Vehicle)vp.param, vp.value);
3229 }
3230
3231 private void changeVehicleRotationParam(strVehicleQuatParam qp)
3232 {
3233 if (m_vehicle == null)
3234 return;
3235 m_vehicle.ProcessRotationVehicleParam((Vehicle)qp.param, qp.value);
3236 }
3237
3238 private void changeVehicleFlags(strVehicleBoolParam bp)
3239 {
3240 if (m_vehicle == null)
3241 return;
3242 m_vehicle.ProcessVehicleFlags(bp.param, bp.value);
3243 }
3244
3245 private void changeBuoyancy(float b)
3246 {
3247 m_buoyancy = b;
3248 }
3249
3250 private void changePIDTarget(Vector3 trg)
3251 {
3252 m_PIDTarget = trg;
3253 }
3254
3255 private void changePIDTau(float tau)
3256 {
3257 m_PIDTau = tau;
3258 }
3259
3260 private void changePIDActive(bool val)
3261 {
3262 m_usePID = val;
3263 }
3264
3265 private void changePIDHoverHeight(float val)
3266 {
3267 m_PIDHoverHeight = val;
3268 if (val == 0)
3269 m_useHoverPID = false;
3270 }
3271
3272 private void changePIDHoverType(PIDHoverType type)
3273 {
3274 m_PIDHoverType = type;
3275 }
3276
3277 private void changePIDHoverTau(float tau)
3278 {
3279 m_PIDHoverTau = tau;
3280 }
3281
3282 private void changePIDHoverActive(bool active)
3283 {
3284 m_useHoverPID = active;
3285 }
3286
3287 #endregion
3288
3289 public void Move()
3290 {
3291 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3292 !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3293 {
3294 if (!d.BodyIsEnabled(Body))
3295 {
3296 // let vehicles sleep
3297 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3298 return;
3299
3300 if (++bodydisablecontrol < 50)
3301 return;
3302
3303 // clear residuals
3304 d.BodySetAngularVel(Body,0f,0f,0f);
3305 d.BodySetLinearVel(Body,0f,0f,0f);
3306 _zeroFlag = true;
3307 d.BodyEnable(Body);
3308 bodydisablecontrol = -4;
3309 }
3310
3311 if(bodydisablecontrol < 0)
3312 bodydisablecontrol ++;
3313
3314 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3315
3316 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3317 {
3318 // 'VEHICLES' are dealt with in ODEDynamics.cs
3319 m_vehicle.Step();
3320 return;
3321 }
3322
3323 float fx = 0;
3324 float fy = 0;
3325 float fz = 0;
3326
3327 float m_mass = _mass;
3328
3329 if (m_usePID && m_PIDTau > 0)
3330 {
3331 // for now position error
3332 _target_velocity =
3333 new Vector3(
3334 (m_PIDTarget.X - lpos.X),
3335 (m_PIDTarget.Y - lpos.Y),
3336 (m_PIDTarget.Z - lpos.Z)
3337 );
3338
3339 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.02f))
3340 {
3341 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3342 d.BodySetLinearVel(Body, 0, 0, 0);
3343 return;
3344 }
3345 else
3346 {
3347 _zeroFlag = false;
3348
3349 float tmp = 1 / m_PIDTau;
3350 _target_velocity *= tmp;
3351
3352 // apply limits
3353 tmp = _target_velocity.Length();
3354 if (tmp > 50.0f)
3355 {
3356 tmp = 50 / tmp;
3357 _target_velocity *= tmp;
3358 }
3359 else if (tmp < 0.05f)
3360 {
3361 tmp = 0.05f / tmp;
3362 _target_velocity *= tmp;
3363 }
3364
3365 d.Vector3 vel = d.BodyGetLinearVel(Body);
3366 fx = (_target_velocity.X - vel.X) * m_invTimeStep;
3367 fy = (_target_velocity.Y - vel.Y) * m_invTimeStep;
3368 fz = (_target_velocity.Z - vel.Z) * m_invTimeStep;
3369// d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z);
3370 }
3371 } // end if (m_usePID)
3372
3373 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3374 else if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
3375 {
3376
3377 // Non-Vehicles have a limited set of Hover options.
3378 // determine what our target height really is based on HoverType
3379
3380 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(lpos.X, lpos.Y);
3381
3382 switch (m_PIDHoverType)
3383 {
3384 case PIDHoverType.Ground:
3385 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3386 break;
3387
3388 case PIDHoverType.GroundAndWater:
3389 m_waterHeight = _parent_scene.GetWaterLevel();
3390 if (m_groundHeight > m_waterHeight)
3391 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3392 else
3393 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3394 break;
3395 } // end switch (m_PIDHoverType)
3396
3397 // don't go underground unless volumedetector
3398
3399 if (m_targetHoverHeight > m_groundHeight || m_isVolumeDetect)
3400 {
3401 d.Vector3 vel = d.BodyGetLinearVel(Body);
3402
3403 fz = (m_targetHoverHeight - lpos.Z);
3404
3405 // if error is zero, use position control; otherwise, velocity control
3406 if (Math.Abs(fz) < 0.01f)
3407 {
3408 d.BodySetPosition(Body, lpos.X, lpos.Y, m_targetHoverHeight);
3409 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3410 }
3411 else
3412 {
3413 _zeroFlag = false;
3414 fz /= m_PIDHoverTau;
3415
3416 float tmp = Math.Abs(fz);
3417 if (tmp > 50)
3418 fz = 50 * Math.Sign(fz);
3419 else if (tmp < 0.1)
3420 fz = 0.1f * Math.Sign(fz);
3421
3422 fz = ((fz - vel.Z) * m_invTimeStep);
3423 }
3424 }
3425 }
3426 else
3427 {
3428 float b = (1.0f - m_buoyancy) * m_gravmod;
3429 fx = _parent_scene.gravityx * b;
3430 fy = _parent_scene.gravityy * b;
3431 fz = _parent_scene.gravityz * b;
3432 }
3433
3434 fx *= m_mass;
3435 fy *= m_mass;
3436 fz *= m_mass;
3437
3438 // constant force
3439 fx += m_force.X;
3440 fy += m_force.Y;
3441 fz += m_force.Z;
3442
3443 fx += m_forceacc.X;
3444 fy += m_forceacc.Y;
3445 fz += m_forceacc.Z;
3446
3447 m_forceacc = Vector3.Zero;
3448
3449 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3450 if (fx != 0 || fy != 0 || fz != 0)
3451 {
3452 d.BodyAddForce(Body, fx, fy, fz);
3453 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3454 }
3455
3456 Vector3 trq;
3457
3458 trq = m_torque;
3459 trq += m_angularForceacc;
3460 m_angularForceacc = Vector3.Zero;
3461 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3462 {
3463 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3464 }
3465 }
3466 else
3467 { // is not physical, or is not a body or is selected
3468 // _zeroPosition = d.BodyGetPosition(Body);
3469 return;
3470 //Console.WriteLine("Nothing " + Name);
3471
3472 }
3473 }
3474
3475 public void UpdatePositionAndVelocity(int frame)
3476 {
3477 if (_parent == null && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero)
3478 {
3479 bool bodyenabled = d.BodyIsEnabled(Body);
3480
3481 if(bodydisablecontrol < 0)
3482 return;
3483
3484 if (bodyenabled || !_zeroFlag)
3485 {
3486 bool lastZeroFlag = _zeroFlag;
3487
3488 d.Vector3 lpos = d.GeomGetPosition(prim_geom);
3489
3490 // check outside region
3491 if (lpos.Z < -100 || lpos.Z > 100000f)
3492 {
3493 m_outbounds = true;
3494
3495 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3496 _acceleration.X = 0;
3497 _acceleration.Y = 0;
3498 _acceleration.Z = 0;
3499
3500 _velocity.X = 0;
3501 _velocity.Y = 0;
3502 _velocity.Z = 0;
3503 m_rotationalVelocity.X = 0;
3504 m_rotationalVelocity.Y = 0;
3505 m_rotationalVelocity.Z = 0;
3506
3507 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3508 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3509 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3510 m_lastposition = _position;
3511 m_lastorientation = _orientation;
3512
3513 base.RequestPhysicsterseUpdate();
3514
3515// throttleCounter = 0;
3516 _zeroFlag = true;
3517
3518 disableBodySoft(); // disable it and colisions
3519 base.RaiseOutOfBounds(_position);
3520 return;
3521 }
3522
3523 if (lpos.X < 0f)
3524 {
3525 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3526 m_outbounds = true;
3527 }
3528 else if (lpos.X > _parent_scene.WorldExtents.X)
3529 {
3530 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3531 m_outbounds = true;
3532 }
3533 if (lpos.Y < 0f)
3534 {
3535 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3536 m_outbounds = true;
3537 }
3538 else if (lpos.Y > _parent_scene.WorldExtents.Y)
3539 {
3540 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3541 m_outbounds = true;
3542 }
3543
3544 if (m_outbounds)
3545 {
3546 m_lastposition = _position;
3547 m_lastorientation = _orientation;
3548
3549 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3550 m_rotationalVelocity.X = dtmp.X;
3551 m_rotationalVelocity.Y = dtmp.Y;
3552 m_rotationalVelocity.Z = dtmp.Z;
3553
3554 dtmp = d.BodyGetLinearVel(Body);
3555 _velocity.X = dtmp.X;
3556 _velocity.Y = dtmp.Y;
3557 _velocity.Z = dtmp.Z;
3558
3559 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3560 d.BodySetAngularVel(Body, 0, 0, 0);
3561 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3562 disableBodySoft(); // stop collisions
3563 UnSubscribeEvents();
3564
3565 base.RequestPhysicsterseUpdate();
3566 return;
3567 }
3568
3569 d.Quaternion ori;
3570 d.GeomCopyQuaternion(prim_geom, out ori);
3571
3572 // decide if moving
3573 // use positions since this are integrated quantities
3574 // tolerance values depende a lot on simulation noise...
3575 // use simple math.abs since we dont need to be exact
3576 if(!bodyenabled)
3577 {
3578 _zeroFlag = true;
3579 }
3580 else
3581 {
3582 float poserror;
3583 float angerror;
3584 if(_zeroFlag)
3585 {
3586 poserror = 0.01f;
3587 angerror = 0.001f;
3588 }
3589 else
3590 {
3591 poserror = 0.005f;
3592 angerror = 0.0005f;
3593 }
3594
3595 if (
3596 (Math.Abs(_position.X - lpos.X) < poserror)
3597 && (Math.Abs(_position.Y - lpos.Y) < poserror)
3598 && (Math.Abs(_position.Z - lpos.Z) < poserror)
3599 && (Math.Abs(_orientation.X - ori.X) < angerror)
3600 && (Math.Abs(_orientation.Y - ori.Y) < angerror)
3601 && (Math.Abs(_orientation.Z - ori.Z) < angerror) // ignore W
3602 )
3603 _zeroFlag = true;
3604 else
3605 _zeroFlag = false;
3606 }
3607
3608 // update position
3609 if (!(_zeroFlag && lastZeroFlag))
3610 {
3611 _position.X = lpos.X;
3612 _position.Y = lpos.Y;
3613 _position.Z = lpos.Z;
3614
3615 _orientation.X = ori.X;
3616 _orientation.Y = ori.Y;
3617 _orientation.Z = ori.Z;
3618 _orientation.W = ori.W;
3619 }
3620
3621 // update velocities and aceleration
3622 if (_zeroFlag || lastZeroFlag)
3623 {
3624 // disable interpolators
3625 _velocity = Vector3.Zero;
3626 _acceleration = Vector3.Zero;
3627 m_rotationalVelocity = Vector3.Zero;
3628 }
3629 else
3630 {
3631 d.Vector3 vel = d.BodyGetLinearVel(Body);
3632
3633 _acceleration = _velocity;
3634
3635 if ((Math.Abs(vel.X) < 0.005f) &&
3636 (Math.Abs(vel.Y) < 0.005f) &&
3637 (Math.Abs(vel.Z) < 0.005f))
3638 {
3639 _velocity = Vector3.Zero;
3640 float t = -m_invTimeStep;
3641 _acceleration = _acceleration * t;
3642 }
3643 else
3644 {
3645 _velocity.X = vel.X;
3646 _velocity.Y = vel.Y;
3647 _velocity.Z = vel.Z;
3648 _acceleration = (_velocity - _acceleration) * m_invTimeStep;
3649 }
3650
3651 if ((Math.Abs(_acceleration.X) < 0.01f) &&
3652 (Math.Abs(_acceleration.Y) < 0.01f) &&
3653 (Math.Abs(_acceleration.Z) < 0.01f))
3654 {
3655 _acceleration = Vector3.Zero;
3656 }
3657
3658 vel = d.BodyGetAngularVel(Body);
3659 if ((Math.Abs(vel.X) < 0.0001) &&
3660 (Math.Abs(vel.Y) < 0.0001) &&
3661 (Math.Abs(vel.Z) < 0.0001)
3662 )
3663 {
3664 m_rotationalVelocity = Vector3.Zero;
3665 }
3666 else
3667 {
3668 m_rotationalVelocity.X = vel.X;
3669 m_rotationalVelocity.Y = vel.Y;
3670 m_rotationalVelocity.Z = vel.Z;
3671 }
3672 }
3673
3674 if (_zeroFlag)
3675 {
3676 if (!m_lastUpdateSent)
3677 {
3678 base.RequestPhysicsterseUpdate();
3679 if (lastZeroFlag)
3680 m_lastUpdateSent = true;
3681 }
3682 return;
3683 }
3684
3685 base.RequestPhysicsterseUpdate();
3686 m_lastUpdateSent = false;
3687 }
3688 }
3689 }
3690
3691 internal static bool QuaternionIsFinite(Quaternion q)
3692 {
3693 if (Single.IsNaN(q.X) || Single.IsInfinity(q.X))
3694 return false;
3695 if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y))
3696 return false;
3697 if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z))
3698 return false;
3699 if (Single.IsNaN(q.W) || Single.IsInfinity(q.W))
3700 return false;
3701 return true;
3702 }
3703
3704 internal static void DMassSubPartFromObj(ref d.Mass part, ref d.Mass theobj)
3705 {
3706 // assumes object center of mass is zero
3707 float smass = part.mass;
3708 theobj.mass -= smass;
3709
3710 smass *= 1.0f / (theobj.mass); ;
3711
3712 theobj.c.X -= part.c.X * smass;
3713 theobj.c.Y -= part.c.Y * smass;
3714 theobj.c.Z -= part.c.Z * smass;
3715
3716 theobj.I.M00 -= part.I.M00;
3717 theobj.I.M01 -= part.I.M01;
3718 theobj.I.M02 -= part.I.M02;
3719 theobj.I.M10 -= part.I.M10;
3720 theobj.I.M11 -= part.I.M11;
3721 theobj.I.M12 -= part.I.M12;
3722 theobj.I.M20 -= part.I.M20;
3723 theobj.I.M21 -= part.I.M21;
3724 theobj.I.M22 -= part.I.M22;
3725 }
3726
3727 private void donullchange()
3728 {
3729 }
3730
3731 public bool DoAChange(changes what, object arg)
3732 {
3733 if (prim_geom == IntPtr.Zero && what != changes.Add && what != changes.AddPhysRep && what != changes.Remove)
3734 {
3735 return false;
3736 }
3737
3738 // nasty switch
3739 switch (what)
3740 {
3741 case changes.Add:
3742 changeadd();
3743 break;
3744
3745 case changes.AddPhysRep:
3746 changeAddPhysRep((ODEPhysRepData)arg);
3747 break;
3748
3749 case changes.Remove:
3750 //If its being removed, we don't want to rebuild the physical rep at all, so ignore this stuff...
3751 //When we return true, it destroys all of the prims in the linkset anyway
3752 if (_parent != null)
3753 {
3754 OdePrim parent = (OdePrim)_parent;
3755 parent.ChildRemove(this, false);
3756 }
3757 else
3758 ChildRemove(this, false);
3759
3760 m_vehicle = null;
3761 RemoveGeom();
3762 m_targetSpace = IntPtr.Zero;
3763 UnSubscribeEvents();
3764 return true;
3765
3766 case changes.Link:
3767 OdePrim tmp = (OdePrim)arg;
3768 changeLink(tmp);
3769 break;
3770
3771 case changes.DeLink:
3772 changeLink(null);
3773 break;
3774
3775 case changes.Position:
3776 changePosition((Vector3)arg);
3777 break;
3778
3779 case changes.Orientation:
3780 changeOrientation((Quaternion)arg);
3781 break;
3782
3783 case changes.PosOffset:
3784 donullchange();
3785 break;
3786
3787 case changes.OriOffset:
3788 donullchange();
3789 break;
3790
3791 case changes.Velocity:
3792 changevelocity((Vector3)arg);
3793 break;
3794
3795// case changes.Acceleration:
3796// changeacceleration((Vector3)arg);
3797// break;
3798
3799 case changes.AngVelocity:
3800 changeangvelocity((Vector3)arg);
3801 break;
3802
3803 case changes.Force:
3804 changeForce((Vector3)arg);
3805 break;
3806
3807 case changes.Torque:
3808 changeSetTorque((Vector3)arg);
3809 break;
3810
3811 case changes.AddForce:
3812 changeAddForce((Vector3)arg);
3813 break;
3814
3815 case changes.AddAngForce:
3816 changeAddAngularImpulse((Vector3)arg);
3817 break;
3818
3819 case changes.AngLock:
3820 changeAngularLock((byte)arg);
3821 break;
3822
3823 case changes.Size:
3824 changeSize((Vector3)arg);
3825 break;
3826
3827 case changes.Shape:
3828 changeShape((PrimitiveBaseShape)arg);
3829 break;
3830
3831 case changes.PhysRepData:
3832 changePhysRepData((ODEPhysRepData) arg);
3833 break;
3834
3835 case changes.CollidesWater:
3836 changeFloatOnWater((bool)arg);
3837 break;
3838
3839 case changes.VolumeDtc:
3840 changeVolumedetetion((bool)arg);
3841 break;
3842
3843 case changes.Phantom:
3844 changePhantomStatus((bool)arg);
3845 break;
3846
3847 case changes.Physical:
3848 changePhysicsStatus((bool)arg);
3849 break;
3850
3851 case changes.Selected:
3852 changeSelectedStatus((bool)arg);
3853 break;
3854
3855 case changes.disabled:
3856 changeDisable((bool)arg);
3857 break;
3858
3859 case changes.building:
3860 changeBuilding((bool)arg);
3861 break;
3862
3863 case changes.VehicleType:
3864 changeVehicleType((int)arg);
3865 break;
3866
3867 case changes.VehicleFlags:
3868 changeVehicleFlags((strVehicleBoolParam) arg);
3869 break;
3870
3871 case changes.VehicleFloatParam:
3872 changeVehicleFloatParam((strVehicleFloatParam) arg);
3873 break;
3874
3875 case changes.VehicleVectorParam:
3876 changeVehicleVectorParam((strVehicleVectorParam) arg);
3877 break;
3878
3879 case changes.VehicleRotationParam:
3880 changeVehicleRotationParam((strVehicleQuatParam) arg);
3881 break;
3882
3883 case changes.SetVehicle:
3884 changeSetVehicle((VehicleData) arg);
3885 break;
3886
3887 case changes.Buoyancy:
3888 changeBuoyancy((float)arg);
3889 break;
3890
3891 case changes.PIDTarget:
3892 changePIDTarget((Vector3)arg);
3893 break;
3894
3895 case changes.PIDTau:
3896 changePIDTau((float)arg);
3897 break;
3898
3899 case changes.PIDActive:
3900 changePIDActive((bool)arg);
3901 break;
3902
3903 case changes.PIDHoverHeight:
3904 changePIDHoverHeight((float)arg);
3905 break;
3906
3907 case changes.PIDHoverType:
3908 changePIDHoverType((PIDHoverType)arg);
3909 break;
3910
3911 case changes.PIDHoverTau:
3912 changePIDHoverTau((float)arg);
3913 break;
3914
3915 case changes.PIDHoverActive:
3916 changePIDHoverActive((bool)arg);
3917 break;
3918
3919 case changes.Null:
3920 donullchange();
3921 break;
3922
3923
3924
3925 default:
3926 donullchange();
3927 break;
3928 }
3929 return false;
3930 }
3931
3932 public void AddChange(changes what, object arg)
3933 {
3934 _parent_scene.AddChange((PhysicsActor) this, what, arg);
3935 }
3936
3937
3938 private struct strVehicleBoolParam
3939 {
3940 public int param;
3941 public bool value;
3942 }
3943
3944 private struct strVehicleFloatParam
3945 {
3946 public int param;
3947 public float value;
3948 }
3949
3950 private struct strVehicleQuatParam
3951 {
3952 public int param;
3953 public Quaternion value;
3954 }
3955
3956 private struct strVehicleVectorParam
3957 {
3958 public int param;
3959 public Vector3 value;
3960 }
3961 }
3962}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
new file mode 100644
index 0000000..b82d593
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODERayCastRequestManager.cs
@@ -0,0 +1,680 @@
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.Runtime.InteropServices;
32using System.Text;
33using OpenSim.Framework;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OdeAPI;
36using log4net;
37using OpenMetaverse;
38
39namespace OpenSim.Region.PhysicsModule.ubOde
40{
41 /// <summary>
42 /// Processes raycast requests as ODE is in a state to be able to do them.
43 /// This ensures that it's thread safe and there will be no conflicts.
44 /// Requests get returned by a different thread then they were requested by.
45 /// </summary>
46 public class ODERayCastRequestManager
47 {
48 /// <summary>
49 /// Pending ray requests
50 /// </summary>
51 protected OpenSim.Framework.LocklessQueue<ODERayRequest> m_PendingRequests = new OpenSim.Framework.LocklessQueue<ODERayRequest>();
52
53 /// <summary>
54 /// Scene that created this object.
55 /// </summary>
56 private ODEScene m_scene;
57
58 IntPtr ray; // the ray. we only need one for our lifetime
59 IntPtr Sphere;
60 IntPtr Box;
61 IntPtr Plane;
62
63 private int CollisionContactGeomsPerTest = 25;
64 private const int DefaultMaxCount = 25;
65 private const int MaxTimePerCallMS = 30;
66
67 /// <summary>
68 /// ODE near callback delegate
69 /// </summary>
70 private d.NearCallback nearCallback;
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 private List<ContactResult> m_contactResults = new List<ContactResult>();
73 private RayFilterFlags CurrentRayFilter;
74 private int CurrentMaxCount;
75
76 public ODERayCastRequestManager(ODEScene pScene)
77 {
78 m_scene = pScene;
79 nearCallback = near;
80 ray = d.CreateRay(IntPtr.Zero, 1.0f);
81 d.GeomSetCategoryBits(ray, 0);
82 Box = d.CreateBox(IntPtr.Zero, 1.0f, 1.0f, 1.0f);
83 d.GeomSetCategoryBits(Box, 0);
84 Sphere = d.CreateSphere(IntPtr.Zero,1.0f);
85 d.GeomSetCategoryBits(Sphere, 0);
86 Plane = d.CreatePlane(IntPtr.Zero, 0f,0f,1f,1f);
87 d.GeomSetCategoryBits(Sphere, 0);
88 }
89
90 public void QueueRequest(ODERayRequest req)
91 {
92 if (req.Count == 0)
93 req.Count = DefaultMaxCount;
94
95 m_PendingRequests.Enqueue(req);
96 }
97
98 /// <summary>
99 /// Process all queued raycast requests
100 /// </summary>
101 /// <returns>Time in MS the raycasts took to process.</returns>
102 public int ProcessQueuedRequests()
103 {
104
105 if (m_PendingRequests.Count <= 0)
106 return 0;
107
108 if (m_scene.ContactgeomsArray == IntPtr.Zero || ray == IntPtr.Zero)
109 // oops something got wrong or scene isn't ready still
110 {
111 m_PendingRequests.Clear();
112 return 0;
113 }
114
115 int time = Util.EnvironmentTickCount();
116
117 ODERayRequest req;
118 int closestHit;
119 int backfacecull;
120 CollisionCategories catflags;
121
122 while (m_PendingRequests.Dequeue(out req))
123 {
124 if (req.callbackMethod != null)
125 {
126 IntPtr geom = IntPtr.Zero;
127 if (req.actor != null)
128 {
129 if (m_scene.haveActor(req.actor))
130 {
131 if (req.actor is OdePrim)
132 geom = ((OdePrim)req.actor).prim_geom;
133 else if (req.actor is OdeCharacter)
134 geom = ((OdePrim)req.actor).prim_geom;
135 }
136 if (geom == IntPtr.Zero)
137 {
138 NoContacts(req);
139 continue;
140 }
141 }
142
143 CurrentRayFilter = req.filter;
144 CurrentMaxCount = req.Count;
145
146 CollisionContactGeomsPerTest = req.Count & 0xffff;
147
148 closestHit = ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0 ? 0 : 1);
149 backfacecull = ((CurrentRayFilter & RayFilterFlags.BackFaceCull) == 0 ? 0 : 1);
150
151 if (req.callbackMethod is ProbeBoxCallback)
152 {
153 if (CollisionContactGeomsPerTest > 80)
154 CollisionContactGeomsPerTest = 80;
155 d.GeomBoxSetLengths(Box, req.Normal.X, req.Normal.Y, req.Normal.Z);
156 d.GeomSetPosition(Box, req.Origin.X, req.Origin.Y, req.Origin.Z);
157 d.Quaternion qtmp;
158 qtmp.X = req.orientation.X;
159 qtmp.Y = req.orientation.Y;
160 qtmp.Z = req.orientation.Z;
161 qtmp.W = req.orientation.W;
162 d.GeomSetQuaternion(Box, ref qtmp);
163 }
164 else if (req.callbackMethod is ProbeSphereCallback)
165 {
166 if (CollisionContactGeomsPerTest > 80)
167 CollisionContactGeomsPerTest = 80;
168
169 d.GeomSphereSetRadius(Sphere, req.length);
170 d.GeomSetPosition(Sphere, req.Origin.X, req.Origin.Y, req.Origin.Z);
171 }
172 else if (req.callbackMethod is ProbePlaneCallback)
173 {
174 if (CollisionContactGeomsPerTest > 80)
175 CollisionContactGeomsPerTest = 80;
176
177 d.GeomPlaneSetParams(Plane, req.Normal.X, req.Normal.Y, req.Normal.Z, req.length);
178 }
179
180 else
181 {
182 if (CollisionContactGeomsPerTest > 25)
183 CollisionContactGeomsPerTest = 25;
184
185 d.GeomRaySetLength(ray, req.length);
186 d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z);
187 d.GeomRaySetParams(ray, 0, backfacecull);
188
189 if (req.callbackMethod is RaycastCallback)
190 {
191 // if we only want one get only one per Collision pair saving memory
192 CurrentRayFilter |= RayFilterFlags.ClosestHit;
193 d.GeomRaySetClosestHit(ray, 1);
194 }
195 else
196 d.GeomRaySetClosestHit(ray, closestHit);
197 }
198
199 if ((CurrentRayFilter & RayFilterFlags.ContactsUnImportant) != 0)
200 unchecked
201 {
202 CollisionContactGeomsPerTest |= (int)d.CONTACTS_UNIMPORTANT;
203 }
204
205 if (geom == IntPtr.Zero)
206 {
207 // translate ray filter to Collision flags
208 catflags = 0;
209 if ((CurrentRayFilter & RayFilterFlags.volumedtc) != 0)
210 catflags |= CollisionCategories.VolumeDtc;
211 if ((CurrentRayFilter & RayFilterFlags.phantom) != 0)
212 catflags |= CollisionCategories.Phantom;
213 if ((CurrentRayFilter & RayFilterFlags.agent) != 0)
214 catflags |= CollisionCategories.Character;
215 if ((CurrentRayFilter & RayFilterFlags.PrimsNonPhantom) != 0)
216 catflags |= CollisionCategories.Geom;
217 if ((CurrentRayFilter & RayFilterFlags.land) != 0)
218 catflags |= CollisionCategories.Land;
219 if ((CurrentRayFilter & RayFilterFlags.water) != 0)
220 catflags |= CollisionCategories.Water;
221
222 if (catflags != 0)
223 {
224 if (req.callbackMethod is ProbeBoxCallback)
225 {
226 catflags |= CollisionCategories.Space;
227 d.GeomSetCollideBits(Box, (uint)catflags);
228 d.GeomSetCategoryBits(Box, (uint)catflags);
229 doProbe(req, Box);
230 }
231 else if (req.callbackMethod is ProbeSphereCallback)
232 {
233 catflags |= CollisionCategories.Space;
234 d.GeomSetCollideBits(Sphere, (uint)catflags);
235 d.GeomSetCategoryBits(Sphere, (uint)catflags);
236 doProbe(req, Sphere);
237 }
238 else if (req.callbackMethod is ProbePlaneCallback)
239 {
240 catflags |= CollisionCategories.Space;
241 d.GeomSetCollideBits(Plane, (uint)catflags);
242 d.GeomSetCategoryBits(Plane, (uint)catflags);
243 doPlane(req,IntPtr.Zero);
244 }
245 else
246 {
247 d.GeomSetCollideBits(ray, (uint)catflags);
248 doSpaceRay(req);
249 }
250 }
251 }
252 else
253 {
254 // if we select a geom don't use filters
255
256 if (req.callbackMethod is ProbePlaneCallback)
257 {
258 d.GeomSetCollideBits(Plane, (uint)CollisionCategories.All);
259 doPlane(req,geom);
260 }
261 else
262 {
263 d.GeomSetCollideBits(ray, (uint)CollisionCategories.All);
264 doGeomRay(req,geom);
265 }
266 }
267 }
268
269 if (Util.EnvironmentTickCountSubtract(time) > MaxTimePerCallMS)
270 break;
271 }
272
273 lock (m_contactResults)
274 m_contactResults.Clear();
275
276 return Util.EnvironmentTickCountSubtract(time);
277 }
278 /// <summary>
279 /// Method that actually initiates the raycast with spaces
280 /// </summary>
281 /// <param name="req"></param>
282 ///
283
284 private void NoContacts(ODERayRequest req)
285 {
286 if (req.callbackMethod is RaycastCallback)
287 {
288 ((RaycastCallback)req.callbackMethod)(false, Vector3.Zero, 0, 0, Vector3.Zero);
289 return;
290 }
291 List<ContactResult> cresult = new List<ContactResult>();
292
293 if (req.callbackMethod is RayCallback)
294 ((RayCallback)req.callbackMethod)(cresult);
295 else if (req.callbackMethod is ProbeBoxCallback)
296 ((ProbeBoxCallback)req.callbackMethod)(cresult);
297 else if (req.callbackMethod is ProbeSphereCallback)
298 ((ProbeSphereCallback)req.callbackMethod)(cresult);
299 }
300
301 private const RayFilterFlags FilterActiveSpace = RayFilterFlags.agent | RayFilterFlags.physical | RayFilterFlags.LSLPhantom;
302// private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.land | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhanton;
303 private const RayFilterFlags FilterStaticSpace = RayFilterFlags.water | RayFilterFlags.nonphysical | RayFilterFlags.LSLPhantom;
304
305 private void doSpaceRay(ODERayRequest req)
306 {
307 // Collide tests
308 if ((CurrentRayFilter & FilterActiveSpace) != 0)
309 {
310 d.SpaceCollide2(ray, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
311 d.SpaceCollide2(ray, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
312 }
313 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
314 d.SpaceCollide2(ray, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
315 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
316 {
317 // current ode land to ray collisions is very bad
318 // so for now limit its range badly
319 if (req.length > 60.0f)
320 d.GeomRaySetLength(ray, 60.0f);
321
322 d.SpaceCollide2(ray, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
323 }
324
325 if (req.callbackMethod is RaycastCallback)
326 {
327 // Define default results
328 bool hitYN = false;
329 uint hitConsumerID = 0;
330 float distance = float.MaxValue;
331 Vector3 closestcontact = Vector3.Zero;
332 Vector3 snormal = Vector3.Zero;
333
334 // Find closest contact and object.
335 lock (m_contactResults)
336 {
337 foreach (ContactResult cResult in m_contactResults)
338 {
339 if(cResult.Depth < distance)
340 {
341 closestcontact = cResult.Pos;
342 hitConsumerID = cResult.ConsumerID;
343 distance = cResult.Depth;
344 snormal = cResult.Normal;
345 }
346 }
347 m_contactResults.Clear();
348 }
349
350 if (distance > 0 && distance < float.MaxValue)
351 hitYN = true;
352 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
353 }
354 else
355 {
356 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
357 lock (m_PendingRequests)
358 {
359 cresult.AddRange(m_contactResults);
360 m_contactResults.Clear();
361 }
362 ((RayCallback)req.callbackMethod)(cresult);
363 }
364 }
365
366 private void doProbe(ODERayRequest req, IntPtr probe)
367 {
368 // Collide tests
369 if ((CurrentRayFilter & FilterActiveSpace) != 0)
370 {
371 d.SpaceCollide2(probe, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
372 d.SpaceCollide2(probe, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
373 }
374 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
375 d.SpaceCollide2(probe, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
376 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
377 d.SpaceCollide2(probe, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
378
379 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
380 lock (m_PendingRequests)
381 {
382 cresult.AddRange(m_contactResults);
383 m_contactResults.Clear();
384 }
385 if (req.callbackMethod is ProbeBoxCallback)
386 ((ProbeBoxCallback)req.callbackMethod)(cresult);
387 else if (req.callbackMethod is ProbeSphereCallback)
388 ((ProbeSphereCallback)req.callbackMethod)(cresult);
389 }
390
391 private void doPlane(ODERayRequest req,IntPtr geom)
392 {
393 // Collide tests
394 if (geom == IntPtr.Zero)
395 {
396 if ((CurrentRayFilter & FilterActiveSpace) != 0)
397 {
398 d.SpaceCollide2(Plane, m_scene.ActiveSpace, IntPtr.Zero, nearCallback);
399 d.SpaceCollide2(Plane, m_scene.CharsSpace, IntPtr.Zero, nearCallback);
400 }
401 if ((CurrentRayFilter & FilterStaticSpace) != 0 && (m_contactResults.Count < CurrentMaxCount))
402 d.SpaceCollide2(Plane, m_scene.StaticSpace, IntPtr.Zero, nearCallback);
403 if ((CurrentRayFilter & RayFilterFlags.land) != 0 && (m_contactResults.Count < CurrentMaxCount))
404 d.SpaceCollide2(Plane, m_scene.GroundSpace, IntPtr.Zero, nearCallback);
405 }
406 else
407 {
408 d.SpaceCollide2(Plane, geom, IntPtr.Zero, nearCallback);
409 }
410
411 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
412 lock (m_PendingRequests)
413 {
414 cresult.AddRange(m_contactResults);
415 m_contactResults.Clear();
416 }
417
418 ((ProbePlaneCallback)req.callbackMethod)(cresult);
419 }
420
421 /// <summary>
422 /// Method that actually initiates the raycast with a geom
423 /// </summary>
424 /// <param name="req"></param>
425 private void doGeomRay(ODERayRequest req, IntPtr geom)
426 {
427 // Collide test
428 d.SpaceCollide2(ray, geom, IntPtr.Zero, nearCallback); // still do this to have full AABB pre test
429
430 if (req.callbackMethod is RaycastCallback)
431 {
432 // Define default results
433 bool hitYN = false;
434 uint hitConsumerID = 0;
435 float distance = float.MaxValue;
436 Vector3 closestcontact = Vector3.Zero;
437 Vector3 snormal = Vector3.Zero;
438
439 // Find closest contact and object.
440 lock (m_contactResults)
441 {
442 foreach (ContactResult cResult in m_contactResults)
443 {
444 if(cResult.Depth < distance )
445 {
446 closestcontact = cResult.Pos;
447 hitConsumerID = cResult.ConsumerID;
448 distance = cResult.Depth;
449 snormal = cResult.Normal;
450 }
451 }
452 m_contactResults.Clear();
453 }
454
455 if (distance > 0 && distance < float.MaxValue)
456 hitYN = true;
457
458 ((RaycastCallback)req.callbackMethod)(hitYN, closestcontact, hitConsumerID, distance, snormal);
459 }
460 else
461 {
462 List<ContactResult> cresult = new List<ContactResult>(m_contactResults.Count);
463 lock (m_PendingRequests)
464 {
465 cresult.AddRange(m_contactResults);
466 m_contactResults.Clear();
467 }
468 ((RayCallback)req.callbackMethod)(cresult);
469 }
470 }
471
472 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
473 {
474 IntPtr ContactgeomsArray = m_scene.ContactgeomsArray;
475 if (ContactgeomsArray == IntPtr.Zero || index >= CollisionContactGeomsPerTest)
476 return false;
477
478 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
479 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
480 return true;
481 }
482
483 // This is the standard Near. g1 is the ray
484 private void near(IntPtr space, IntPtr g1, IntPtr g2)
485 {
486 if (g2 == IntPtr.Zero || g1 == g2)
487 return;
488
489 if (m_contactResults.Count >= CurrentMaxCount)
490 return;
491
492 if (d.GeomIsSpace(g2))
493 {
494 try
495 {
496 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
497 }
498 catch (Exception e)
499 {
500 m_log.WarnFormat("[PHYSICS Ray]: Unable to Space collide test an object: {0}", e.Message);
501 }
502 return;
503 }
504
505 int count = 0;
506 try
507 {
508 count = d.CollidePtr(g1, g2, CollisionContactGeomsPerTest, m_scene.ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
509 }
510 catch (Exception e)
511 {
512 m_log.WarnFormat("[PHYSICS Ray]: Unable to collide test an object: {0}", e.Message);
513 return;
514 }
515
516 if (count == 0)
517 return;
518/*
519 uint cat1 = d.GeomGetCategoryBits(g1);
520 uint cat2 = d.GeomGetCategoryBits(g2);
521 uint col1 = d.GeomGetCollideBits(g1);
522 uint col2 = d.GeomGetCollideBits(g2);
523*/
524
525 uint ID = 0;
526 PhysicsActor p2 = null;
527
528 m_scene.actor_name_map.TryGetValue(g2, out p2);
529
530 if (p2 == null)
531 return;
532
533 switch (p2.PhysicsActorType)
534 {
535 case (int)ActorTypes.Prim:
536
537 RayFilterFlags thisFlags;
538
539 if (p2.IsPhysical)
540 thisFlags = RayFilterFlags.physical;
541 else
542 thisFlags = RayFilterFlags.nonphysical;
543
544 if (p2.Phantom)
545 thisFlags |= RayFilterFlags.phantom;
546
547 if (p2.IsVolumeDtc)
548 thisFlags |= RayFilterFlags.volumedtc;
549
550 if ((thisFlags & CurrentRayFilter) == 0)
551 return;
552
553 ID = ((OdePrim)p2).LocalID;
554 break;
555
556 case (int)ActorTypes.Agent:
557
558 if ((CurrentRayFilter & RayFilterFlags.agent) == 0)
559 return;
560 else
561 ID = ((OdeCharacter)p2).LocalID;
562 break;
563
564 case (int)ActorTypes.Ground:
565
566 if ((CurrentRayFilter & RayFilterFlags.land) == 0)
567 return;
568 break;
569
570 case (int)ActorTypes.Water:
571
572 if ((CurrentRayFilter & RayFilterFlags.water) == 0)
573 return;
574 break;
575
576 default:
577 break;
578 }
579
580 d.ContactGeom curcontact = new d.ContactGeom();
581
582 // closestHit for now only works for meshs, so must do it for others
583 if ((CurrentRayFilter & RayFilterFlags.ClosestHit) == 0)
584 {
585 // Loop all contacts, build results.
586 for (int i = 0; i < count; i++)
587 {
588 if (!GetCurContactGeom(i, ref curcontact))
589 break;
590
591 ContactResult collisionresult = new ContactResult();
592 collisionresult.ConsumerID = ID;
593 collisionresult.Pos.X = curcontact.pos.X;
594 collisionresult.Pos.Y = curcontact.pos.Y;
595 collisionresult.Pos.Z = curcontact.pos.Z;
596 collisionresult.Depth = curcontact.depth;
597 collisionresult.Normal.X = curcontact.normal.X;
598 collisionresult.Normal.Y = curcontact.normal.Y;
599 collisionresult.Normal.Z = curcontact.normal.Z;
600 lock (m_contactResults)
601 {
602 m_contactResults.Add(collisionresult);
603 if (m_contactResults.Count >= CurrentMaxCount)
604 return;
605 }
606 }
607 }
608 else
609 {
610 // keep only closest contact
611 ContactResult collisionresult = new ContactResult();
612 collisionresult.ConsumerID = ID;
613 collisionresult.Depth = float.MaxValue;
614
615 for (int i = 0; i < count; i++)
616 {
617 if (!GetCurContactGeom(i, ref curcontact))
618 break;
619
620 if (curcontact.depth < collisionresult.Depth)
621 {
622 collisionresult.Pos.X = curcontact.pos.X;
623 collisionresult.Pos.Y = curcontact.pos.Y;
624 collisionresult.Pos.Z = curcontact.pos.Z;
625 collisionresult.Depth = curcontact.depth;
626 collisionresult.Normal.X = curcontact.normal.X;
627 collisionresult.Normal.Y = curcontact.normal.Y;
628 collisionresult.Normal.Z = curcontact.normal.Z;
629 }
630 }
631
632 if (collisionresult.Depth != float.MaxValue)
633 {
634 lock (m_contactResults)
635 m_contactResults.Add(collisionresult);
636 }
637 }
638 }
639
640 /// <summary>
641 /// Dereference the creator scene so that it can be garbage collected if needed.
642 /// </summary>
643 internal void Dispose()
644 {
645 m_scene = null;
646 if (ray != IntPtr.Zero)
647 {
648 d.GeomDestroy(ray);
649 ray = IntPtr.Zero;
650 }
651 if (Box != IntPtr.Zero)
652 {
653 d.GeomDestroy(Box);
654 Box = IntPtr.Zero;
655 }
656 if (Sphere != IntPtr.Zero)
657 {
658 d.GeomDestroy(Sphere);
659 Sphere = IntPtr.Zero;
660 }
661 if (Plane != IntPtr.Zero)
662 {
663 d.GeomDestroy(Plane);
664 Plane = IntPtr.Zero;
665 }
666 }
667 }
668
669 public struct ODERayRequest
670 {
671 public PhysicsActor actor;
672 public Vector3 Origin;
673 public Vector3 Normal;
674 public int Count;
675 public float length;
676 public object callbackMethod;
677 public RayFilterFlags filter;
678 public Quaternion orientation;
679 }
680}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
new file mode 100644
index 0000000..61e31a1
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs
@@ -0,0 +1,2830 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28// Revision 2011/12/13 by Ubit Umarov
29//#define SPAM
30
31using System;
32using System.Collections.Generic;
33using System.Reflection;
34using System.Runtime.InteropServices;
35using System.Threading;
36using System.IO;
37using System.Diagnostics;
38using log4net;
39using Nini.Config;
40using Mono.Addins;
41using OdeAPI;
42using OpenSim.Framework;
43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.PhysicsModules.SharedBase;
46using OpenMetaverse;
47
48namespace OpenSim.Region.PhysicsModule.ubOde
49{
50 // colision flags of things others can colide with
51 // rays, sensors, probes removed since can't be colided with
52 // The top space where things are placed provided further selection
53 // ie physical are in active space nonphysical in static
54 // this should be exclusive as possible
55
56 [Flags]
57 public enum CollisionCategories : uint
58 {
59 Disabled = 0,
60 //by 'things' types
61 Space = 0x01,
62 Geom = 0x02, // aka prim/part
63 Character = 0x04,
64 Land = 0x08,
65 Water = 0x010,
66
67 // by state
68 Phantom = 0x01000,
69 VolumeDtc = 0x02000,
70 Selected = 0x04000,
71 NoShape = 0x08000,
72
73
74 All = 0xffffffff
75 }
76
77 /// <summary>
78 /// Material type for a primitive
79 /// </summary>
80 public enum Material : int
81 {
82 /// <summary></summary>
83 Stone = 0,
84 /// <summary></summary>
85 Metal = 1,
86 /// <summary></summary>
87 Glass = 2,
88 /// <summary></summary>
89 Wood = 3,
90 /// <summary></summary>
91 Flesh = 4,
92 /// <summary></summary>
93 Plastic = 5,
94 /// <summary></summary>
95 Rubber = 6,
96
97 light = 7 // compatibility with old viewers
98 }
99
100 public enum changes : int
101 {
102 Add = 0, // arg null. finishs the prim creation. should be used internally only ( to remove later ?)
103 Remove,
104 Link, // arg AuroraODEPrim new parent prim or null to delink. Makes the prim part of a object with prim parent as root
105 // or removes from a object if arg is null
106 DeLink,
107 Position, // arg Vector3 new position in world coords. Changes prim position. Prim must know if it is root or child
108 Orientation, // arg Quaternion new orientation in world coords. Changes prim position. Prim must know it it is root or child
109 PosOffset, // not in use
110 // arg Vector3 new position in local coords. Changes prim position in object
111 OriOffset, // not in use
112 // arg Vector3 new position in local coords. Changes prim position in object
113 Velocity,
114 AngVelocity,
115 Acceleration,
116 Force,
117 Torque,
118 Momentum,
119
120 AddForce,
121 AddAngForce,
122 AngLock,
123
124 Buoyancy,
125
126 PIDTarget,
127 PIDTau,
128 PIDActive,
129
130 PIDHoverHeight,
131 PIDHoverType,
132 PIDHoverTau,
133 PIDHoverActive,
134
135 Size,
136 AvatarSize,
137 Shape,
138 PhysRepData,
139 AddPhysRep,
140
141 CollidesWater,
142 VolumeDtc,
143
144 Physical,
145 Phantom,
146 Selected,
147 disabled,
148 building,
149
150 VehicleType,
151 VehicleFloatParam,
152 VehicleVectorParam,
153 VehicleRotationParam,
154 VehicleFlags,
155 SetVehicle,
156
157 Null //keep this last used do dim the methods array. does nothing but pulsing the prim
158 }
159
160 public struct ODEchangeitem
161 {
162 public PhysicsActor actor;
163 public OdeCharacter character;
164 public changes what;
165 public Object arg;
166 }
167
168 public class ODEScene : PhysicsScene
169 {
170 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
171
172 public bool m_OSOdeLib = false;
173 public bool m_suportCombine = false; // mega suport not tested
174 public Scene m_frameWorkScene = null;
175
176// private int threadid = 0;
177
178// const d.ContactFlags comumContactFlags = d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM |d.ContactFlags.Approx1 | d.ContactFlags.Bounce;
179
180 const d.ContactFlags comumContactFlags = d.ContactFlags.Bounce | d.ContactFlags.Approx1 | d.ContactFlags.Slip1 | d.ContactFlags.Slip2;
181 const float comumContactERP = 0.75f;
182 const float comumContactCFM = 0.0001f;
183 const float comumContactSLIP = 0f;
184
185 float frictionMovementMult = 0.8f;
186
187 float TerrainBounce = 0.1f;
188 float TerrainFriction = 0.3f;
189
190 public float AvatarFriction = 0;// 0.9f * 0.5f;
191
192 // this netx dimensions are only relevant for terrain partition (mega regions)
193 // WorldExtents below has the simulation dimensions
194 // they should be identical except on mega regions
195 private uint m_regionWidth = Constants.RegionSize;
196 private uint m_regionHeight = Constants.RegionSize;
197
198 public float ODE_STEPSIZE = 0.020f;
199 public float HalfOdeStep = 0.01f;
200 public int odetimestepMS = 20; // rounded
201 private float metersInSpace = 25.6f;
202 private float m_timeDilation = 1.0f;
203
204 private DateTime m_lastframe;
205 private DateTime m_lastMeshExpire;
206
207 public float gravityx = 0f;
208 public float gravityy = 0f;
209 public float gravityz = -9.8f;
210
211 private float waterlevel = 0f;
212 private int framecount = 0;
213
214 private float avDensity = 80f;
215 private float avMovementDivisorWalk = 1.3f;
216 private float avMovementDivisorRun = 0.8f;
217 private float minimumGroundFlightOffset = 3f;
218 public float maximumMassObject = 10000.01f;
219 public float geomDefaultDensity = 10.0f;
220
221 public float maximumAngularVelocity = 12.0f; // default 12rad/s
222 public float maxAngVelocitySQ = 144f; // squared value
223
224 public float bodyPIDD = 35f;
225 public float bodyPIDG = 25;
226
227 public int bodyFramesAutoDisable = 5;
228
229 private d.NearCallback nearCallback;
230
231 private HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
232 private HashSet<OdePrim> _prims = new HashSet<OdePrim>();
233 private HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
234 private HashSet<OdePrim> _activegroups = new HashSet<OdePrim>();
235
236 public OpenSim.Framework.LocklessQueue<ODEchangeitem> ChangesQueue = new OpenSim.Framework.LocklessQueue<ODEchangeitem>();
237
238 /// <summary>
239 /// A list of actors that should receive collision events.
240 /// </summary>
241 private List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
242 private List<PhysicsActor> _collisionEventPrimRemove = new List<PhysicsActor>();
243
244 private HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
245 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
246
247 private float contactsurfacelayer = 0.002f;
248
249 private int contactsPerCollision = 80;
250 internal IntPtr ContactgeomsArray = IntPtr.Zero;
251 private IntPtr GlobalContactsArray = IntPtr.Zero;
252 private d.Contact SharedTmpcontact = new d.Contact();
253
254 const int maxContactsbeforedeath = 6000;
255 private volatile int m_global_contactcount = 0;
256
257 private IntPtr contactgroup;
258
259 public ContactData[] m_materialContactsData = new ContactData[8];
260
261 private Dictionary<Vector3, IntPtr> RegionTerrain = new Dictionary<Vector3, IntPtr>();
262 private Dictionary<IntPtr, float[]> TerrainHeightFieldHeights = new Dictionary<IntPtr, float[]>();
263 private Dictionary<IntPtr, GCHandle> TerrainHeightFieldHeightsHandlers = new Dictionary<IntPtr, GCHandle>();
264
265 private int m_physicsiterations = 15;
266 private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
267// private PhysicsActor PANull = new NullPhysicsActor();
268 private float step_time = 0.0f;
269
270 public IntPtr world;
271
272 // split the spaces acording to contents type
273 // ActiveSpace contains characters and active prims
274 // StaticSpace contains land and other that is mostly static in enviroment
275 // this can contain subspaces, like the grid in staticspace
276 // as now space only contains this 2 top spaces
277
278 public IntPtr TopSpace; // the global space
279 public IntPtr ActiveSpace; // space for active prims
280 public IntPtr CharsSpace; // space for active prims
281 public IntPtr StaticSpace; // space for the static things around
282 public IntPtr GroundSpace; // space for ground
283
284 // some speedup variables
285 private int spaceGridMaxX;
286 private int spaceGridMaxY;
287 private float spacesPerMeterX;
288 private float spacesPerMeterY;
289
290 // split static geometry collision into a grid as before
291 private IntPtr[,] staticPrimspace;
292 private IntPtr[] staticPrimspaceOffRegion;
293
294 public Object OdeLock;
295 public static Object SimulationLock;
296
297 public IMesher mesher;
298
299 public IConfigSource m_config;
300
301 public bool physics_logging = false;
302 public int physics_logging_interval = 0;
303 public bool physics_logging_append_existing_logfile = false;
304
305 private Vector3 m_worldOffset = Vector3.Zero;
306 public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
307 private PhysicsScene m_parentScene = null;
308
309 private ODERayCastRequestManager m_rayCastManager;
310 public ODEMeshWorker m_meshWorker;
311
312 /* maybe needed if ode uses tls
313 private void checkThread()
314 {
315
316 int th = Thread.CurrentThread.ManagedThreadId;
317 if(th != threadid)
318 {
319 threadid = th;
320 d.AllocateODEDataForThread(~0U);
321 }
322 }
323 */
324
325 IConfig physicsconfig = null;
326
327 public ODEScene(Scene pscene, IConfigSource psourceconfig, string pname, bool pOSOdeLib)
328 {
329 OdeLock = new Object();
330
331 EngineType = pname;
332 PhysicsSceneName = EngineType + "/" + pscene.RegionInfo.RegionName;
333
334 m_config = psourceconfig;
335 m_OSOdeLib = pOSOdeLib;
336
337// m_OSOdeLib = false; //debug
338
339 m_frameWorkScene = pscene;
340
341 m_frameWorkScene.RegisterModuleInterface<PhysicsScene>(this);
342
343 Initialization();
344
345 base.Initialise(m_frameWorkScene.PhysicsRequestAsset,
346 (m_frameWorkScene.Heightmap != null ? m_frameWorkScene.Heightmap.GetFloatsSerialised() : new float[m_frameWorkScene.RegionInfo.RegionSizeX * m_frameWorkScene.RegionInfo.RegionSizeY]),
347 (float)m_frameWorkScene.RegionInfo.RegionSettings.WaterHeight);
348 }
349
350 public void RegionLoaded()
351 {
352 mesher = m_frameWorkScene.RequestModuleInterface<IMesher>();
353 if (mesher == null)
354 {
355 m_log.ErrorFormat("[ubOde] No mesher. module disabled");
356 return;
357 }
358
359 m_meshWorker = new ODEMeshWorker(this, m_log, mesher, physicsconfig);
360 m_frameWorkScene.PhysicsEnabled = true;
361 }
362 /// <summary>
363 /// Initiailizes the scene
364 /// Sets many properties that ODE requires to be stable
365 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
366 /// </summary>
367 private void Initialization()
368 {
369 // checkThread();
370 SimulationLock = new Object();
371
372 nearCallback = near;
373
374 m_rayCastManager = new ODERayCastRequestManager(this);
375
376 WorldExtents.X = m_frameWorkScene.RegionInfo.RegionSizeX;
377 m_regionWidth = (uint)WorldExtents.X;
378 WorldExtents.Y = m_frameWorkScene.RegionInfo.RegionSizeY;
379 m_regionHeight = (uint)WorldExtents.Y;
380
381 m_suportCombine = false;
382
383 lock (OdeLock)
384 {
385 // Create the world and the first space
386 try
387 {
388 world = d.WorldCreate();
389 TopSpace = d.HashSpaceCreate(IntPtr.Zero);
390
391 // now the major subspaces
392 ActiveSpace = d.HashSpaceCreate(TopSpace);
393 CharsSpace = d.HashSpaceCreate(TopSpace);
394 StaticSpace = d.HashSpaceCreate(TopSpace);
395 GroundSpace = d.HashSpaceCreate(TopSpace);
396 }
397 catch
398 {
399 // i must RtC#FM
400 // i did!
401 }
402
403 d.HashSpaceSetLevels(TopSpace, -5, 12);
404 d.HashSpaceSetLevels(ActiveSpace, -5, 10);
405 d.HashSpaceSetLevels(CharsSpace, -4, 3);
406 d.HashSpaceSetLevels(StaticSpace, -5, 12);
407 d.HashSpaceSetLevels(GroundSpace, 0, 8);
408
409 // demote to second level
410 d.SpaceSetSublevel(ActiveSpace, 1);
411 d.SpaceSetSublevel(CharsSpace, 1);
412 d.SpaceSetSublevel(StaticSpace, 1);
413 d.SpaceSetSublevel(GroundSpace, 1);
414
415 d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
416 CollisionCategories.Geom |
417 CollisionCategories.Character |
418 CollisionCategories.Phantom |
419 CollisionCategories.VolumeDtc
420 ));
421 d.GeomSetCollideBits(ActiveSpace, (uint)(CollisionCategories.Space |
422 CollisionCategories.Geom |
423 CollisionCategories.Character |
424 CollisionCategories.Phantom |
425 CollisionCategories.VolumeDtc
426 ));
427 d.GeomSetCategoryBits(CharsSpace, (uint)(CollisionCategories.Space |
428 CollisionCategories.Geom |
429 CollisionCategories.Character |
430 CollisionCategories.Phantom |
431 CollisionCategories.VolumeDtc
432 ));
433 d.GeomSetCollideBits(CharsSpace, 0);
434
435 d.GeomSetCategoryBits(StaticSpace, (uint)(CollisionCategories.Space |
436 CollisionCategories.Geom |
437 // CollisionCategories.Land |
438 // CollisionCategories.Water |
439 CollisionCategories.Phantom |
440 CollisionCategories.VolumeDtc
441 ));
442 d.GeomSetCollideBits(StaticSpace, 0);
443
444 d.GeomSetCategoryBits(GroundSpace, (uint)(CollisionCategories.Land));
445 d.GeomSetCollideBits(GroundSpace, 0);
446
447 contactgroup = d.JointGroupCreate(maxContactsbeforedeath + 1);
448 //contactgroup
449
450 d.WorldSetAutoDisableFlag(world, false);
451 }
452
453
454 // checkThread();
455
456
457 // Defaults
458
459 int contactsPerCollision = 80;
460
461 physicsconfig = null;
462
463 if (m_config != null)
464 {
465 physicsconfig = m_config.Configs["ODEPhysicsSettings"];
466 if (physicsconfig != null)
467 {
468 gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
469 gravityy = physicsconfig.GetFloat("world_gravityy", gravityy);
470 gravityz = physicsconfig.GetFloat("world_gravityz", gravityz);
471
472 metersInSpace = physicsconfig.GetFloat("meters_in_small_space", metersInSpace);
473
474 // contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", contactsurfacelayer);
475
476 ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", ODE_STEPSIZE);
477
478 avDensity = physicsconfig.GetFloat("av_density", avDensity);
479 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", avMovementDivisorWalk);
480 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", avMovementDivisorRun);
481
482 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision);
483
484 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
485 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
486
487 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
488 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
489 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
490
491 minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", minimumGroundFlightOffset);
492 maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", maximumMassObject);
493
494 avDensity *= 3f / 80f; // scale other engines density option to this
495 }
496 }
497
498 float heartbeat = 1/m_frameWorkScene.FrameTime;
499 maximumAngularVelocity = 0.49f * heartbeat *(float)Math.PI;
500 maxAngVelocitySQ = maximumAngularVelocity * maximumAngularVelocity;
501
502 d.WorldSetCFM(world, comumContactCFM);
503 d.WorldSetERP(world, comumContactERP);
504
505 d.WorldSetGravity(world, gravityx, gravityy, gravityz);
506
507 d.WorldSetLinearDamping(world, 0.002f);
508 d.WorldSetAngularDamping(world, 0.002f);
509 d.WorldSetAngularDampingThreshold(world, 0f);
510 d.WorldSetLinearDampingThreshold(world, 0f);
511 d.WorldSetMaxAngularSpeed(world, maximumAngularVelocity);
512
513 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
514
515 d.WorldSetContactSurfaceLayer(world, contactsurfacelayer);
516 d.WorldSetContactMaxCorrectingVel(world, 60.0f);
517
518 HalfOdeStep = ODE_STEPSIZE * 0.5f;
519 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE + 0.5f);
520
521 ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf);
522 GlobalContactsArray = Marshal.AllocHGlobal((maxContactsbeforedeath + 100) * d.Contact.unmanagedSizeOf);
523
524 SharedTmpcontact.geom.g1 = IntPtr.Zero;
525 SharedTmpcontact.geom.g2 = IntPtr.Zero;
526
527 SharedTmpcontact.geom.side1 = -1;
528 SharedTmpcontact.geom.side2 = -1;
529
530 SharedTmpcontact.surface.mode = comumContactFlags;
531 SharedTmpcontact.surface.mu = 0;
532 SharedTmpcontact.surface.bounce = 0;
533 SharedTmpcontact.surface.soft_cfm = comumContactCFM;
534 SharedTmpcontact.surface.soft_erp = comumContactERP;
535 SharedTmpcontact.surface.slip1 = comumContactSLIP;
536 SharedTmpcontact.surface.slip2 = comumContactSLIP;
537
538 m_materialContactsData[(int)Material.Stone].mu = 0.8f;
539 m_materialContactsData[(int)Material.Stone].bounce = 0.4f;
540
541 m_materialContactsData[(int)Material.Metal].mu = 0.3f;
542 m_materialContactsData[(int)Material.Metal].bounce = 0.4f;
543
544 m_materialContactsData[(int)Material.Glass].mu = 0.2f;
545 m_materialContactsData[(int)Material.Glass].bounce = 0.7f;
546
547 m_materialContactsData[(int)Material.Wood].mu = 0.6f;
548 m_materialContactsData[(int)Material.Wood].bounce = 0.5f;
549
550 m_materialContactsData[(int)Material.Flesh].mu = 0.9f;
551 m_materialContactsData[(int)Material.Flesh].bounce = 0.3f;
552
553 m_materialContactsData[(int)Material.Plastic].mu = 0.4f;
554 m_materialContactsData[(int)Material.Plastic].bounce = 0.7f;
555
556 m_materialContactsData[(int)Material.Rubber].mu = 0.9f;
557 m_materialContactsData[(int)Material.Rubber].bounce = 0.95f;
558
559 m_materialContactsData[(int)Material.light].mu = 0.0f;
560 m_materialContactsData[(int)Material.light].bounce = 0.0f;
561
562
563 spacesPerMeterX = 1.0f / metersInSpace;
564 spacesPerMeterY = spacesPerMeterX;
565 spaceGridMaxX = (int)(WorldExtents.X * spacesPerMeterX);
566 spaceGridMaxY = (int)(WorldExtents.Y * spacesPerMeterY);
567
568 if (spaceGridMaxX > 24)
569 {
570 spaceGridMaxX = 24;
571 spacesPerMeterX = spaceGridMaxX / WorldExtents.X;
572 }
573
574 if (spaceGridMaxY > 24)
575 {
576 spaceGridMaxY = 24;
577 spacesPerMeterY = spaceGridMaxY / WorldExtents.Y;
578 }
579
580 staticPrimspace = new IntPtr[spaceGridMaxX, spaceGridMaxY];
581
582 // create all spaces now
583 int i, j;
584 IntPtr newspace;
585
586 for (i = 0; i < spaceGridMaxX; i++)
587 for (j = 0; j < spaceGridMaxY; j++)
588 {
589 newspace = d.HashSpaceCreate(StaticSpace);
590 d.GeomSetCategoryBits(newspace, (int)CollisionCategories.Space);
591 waitForSpaceUnlock(newspace);
592 d.SpaceSetSublevel(newspace, 2);
593 d.HashSpaceSetLevels(newspace, -2, 8);
594 d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
595 CollisionCategories.Geom |
596 CollisionCategories.Land |
597 CollisionCategories.Water |
598 CollisionCategories.Phantom |
599 CollisionCategories.VolumeDtc
600 ));
601 d.GeomSetCollideBits(newspace, 0);
602
603 staticPrimspace[i, j] = newspace;
604 }
605
606 // let this now be index limit
607 spaceGridMaxX--;
608 spaceGridMaxY--;
609
610 // create 4 off world spaces (x<0,x>max,y<0,y>max)
611 staticPrimspaceOffRegion = new IntPtr[4];
612
613 for (i = 0; i < 4; i++)
614 {
615 newspace = d.HashSpaceCreate(StaticSpace);
616 d.GeomSetCategoryBits(newspace, (int)CollisionCategories.Space);
617 waitForSpaceUnlock(newspace);
618 d.SpaceSetSublevel(newspace, 2);
619 d.HashSpaceSetLevels(newspace, -2, 8);
620 d.GeomSetCategoryBits(newspace, (uint)(CollisionCategories.Space |
621 CollisionCategories.Geom |
622 CollisionCategories.Land |
623 CollisionCategories.Water |
624 CollisionCategories.Phantom |
625 CollisionCategories.VolumeDtc
626 ));
627 d.GeomSetCollideBits(newspace, 0);
628
629 staticPrimspaceOffRegion[i] = newspace;
630 }
631
632 m_lastframe = DateTime.UtcNow;
633 m_lastMeshExpire = m_lastframe;
634 }
635
636 internal void waitForSpaceUnlock(IntPtr space)
637 {
638 //if (space != IntPtr.Zero)
639 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
640 }
641
642 #region Collision Detection
643
644 // sets a global contact for a joint for contactgeom , and base contact description)
645 private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom,bool smooth)
646 {
647 if (m_global_contactcount >= maxContactsbeforedeath)
648 return IntPtr.Zero;
649
650 m_global_contactcount++;
651 if(smooth)
652 SharedTmpcontact.geom.depth = contactGeom.depth * 0.05f;
653 else
654 SharedTmpcontact.geom.depth = contactGeom.depth;
655 SharedTmpcontact.geom.pos = contactGeom.pos;
656 SharedTmpcontact.geom.normal = contactGeom.normal;
657
658 IntPtr contact = new IntPtr(GlobalContactsArray.ToInt64() + (Int64)(m_global_contactcount * d.Contact.unmanagedSizeOf));
659 Marshal.StructureToPtr(SharedTmpcontact, contact, true);
660 return d.JointCreateContactPtr(world, contactgroup, contact);
661 }
662
663 private bool GetCurContactGeom(int index, ref d.ContactGeom newcontactgeom)
664 {
665 if (ContactgeomsArray == IntPtr.Zero || index >= contactsPerCollision)
666 return false;
667
668 IntPtr contactptr = new IntPtr(ContactgeomsArray.ToInt64() + (Int64)(index * d.ContactGeom.unmanagedSizeOf));
669 newcontactgeom = (d.ContactGeom)Marshal.PtrToStructure(contactptr, typeof(d.ContactGeom));
670 return true;
671 }
672
673 /// <summary>
674 /// This is our near callback. A geometry is near a body
675 /// </summary>
676 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
677 /// <param name="g1">a geometry or space</param>
678 /// <param name="g2">another geometry or space</param>
679 ///
680
681 private void near(IntPtr space, IntPtr g1, IntPtr g2)
682 {
683 // no lock here! It's invoked from within Simulate(), which is thread-locked
684
685 if (m_global_contactcount >= maxContactsbeforedeath)
686 return;
687
688 // Test if we're colliding a geom with a space.
689 // If so we have to drill down into the space recursively
690
691 if (g1 == IntPtr.Zero || g2 == IntPtr.Zero)
692 return;
693
694 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
695 {
696 // We'll be calling near recursivly if one
697 // of them is a space to find all of the
698 // contact points in the space
699 try
700 {
701 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
702 }
703 catch (AccessViolationException)
704 {
705 m_log.Warn("[PHYSICS]: Unable to collide test a space");
706 return;
707 }
708 //here one should check collisions of geoms inside a space
709 // but on each space we only should have geoms that not colide amoung each other
710 // so we don't dig inside spaces
711 return;
712 }
713
714 // get geom bodies to check if we already a joint contact
715 // guess this shouldn't happen now
716 IntPtr b1 = d.GeomGetBody(g1);
717 IntPtr b2 = d.GeomGetBody(g2);
718
719 // d.GeomClassID id = d.GeomGetClass(g1);
720
721 // Figure out how many contact points we have
722 int count = 0;
723 try
724 {
725 // Colliding Geom To Geom
726 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
727
728 if (g1 == g2)
729 return; // Can't collide with yourself
730
731 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
732 return;
733 /*
734 // debug
735 PhysicsActor dp2;
736 if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass)
737 {
738 d.AABB aabb;
739 d.GeomGetAABB(g2, out aabb);
740 float x = aabb.MaxX - aabb.MinX;
741 float y = aabb.MaxY - aabb.MinY;
742 float z = aabb.MaxZ - aabb.MinZ;
743 if (x > 60.0f || y > 60.0f || z > 60.0f)
744 {
745 if (!actor_name_map.TryGetValue(g2, out dp2))
746 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
747 else
748 m_log.WarnFormat("[PHYSICS]: land versus large prim geo {0},size {1}, AABBsize <{2},{3},{4}>, at {5} ori {6},({7})",
749 dp2.Name, dp2.Size, x, y, z,
750 dp2.Position.ToString(),
751 dp2.Orientation.ToString(),
752 dp2.Orientation.Length());
753 return;
754 }
755 }
756 //
757 */
758
759
760 if (d.GeomGetCategoryBits(g1) == (uint)CollisionCategories.VolumeDtc ||
761 d.GeomGetCategoryBits(g2) == (uint)CollisionCategories.VolumeDtc)
762 {
763 int cflags;
764 unchecked
765 {
766 cflags = (int)(1 | d.CONTACTS_UNIMPORTANT);
767 }
768 count = d.CollidePtr(g1, g2, cflags, ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
769 }
770 else
771 count = d.CollidePtr(g1, g2, (contactsPerCollision & 0xffff), ContactgeomsArray, d.ContactGeom.unmanagedSizeOf);
772 }
773 catch (SEHException)
774 {
775 m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
776 // ode.drelease(world);
777 base.TriggerPhysicsBasedRestart();
778 }
779 catch (Exception e)
780 {
781 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message);
782 return;
783 }
784
785 // contacts done
786 if (count == 0)
787 return;
788
789 // try get physical actors
790 PhysicsActor p1;
791 PhysicsActor p2;
792
793 if (!actor_name_map.TryGetValue(g1, out p1))
794 {
795 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 1");
796 return;
797 }
798
799 if (!actor_name_map.TryGetValue(g2, out p2))
800 {
801 m_log.WarnFormat("[PHYSICS]: failed actor mapping for geom 2");
802 return;
803 }
804
805 // update actors collision score
806 if (p1.CollisionScore >= float.MaxValue - count)
807 p1.CollisionScore = 0;
808 p1.CollisionScore += count;
809
810 if (p2.CollisionScore >= float.MaxValue - count)
811 p2.CollisionScore = 0;
812 p2.CollisionScore += count;
813
814 // get first contact
815 d.ContactGeom curContact = new d.ContactGeom();
816
817 if (!GetCurContactGeom(0, ref curContact))
818 return;
819
820 ContactPoint maxDepthContact = new ContactPoint();
821
822 // do volume detection case
823 if ((p1.IsVolumeDtc || p2.IsVolumeDtc))
824 {
825 maxDepthContact = new ContactPoint(
826 new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z),
827 new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z),
828 curContact.depth, false
829 );
830
831 collision_accounting_events(p1, p2, maxDepthContact);
832 return;
833 }
834
835 // big messy collision analises
836
837 float mu = 0;
838 float bounce = 0;
839// bool IgnoreNegSides = false;
840
841 ContactData contactdata1 = new ContactData(0, 0, false);
842 ContactData contactdata2 = new ContactData(0, 0, false);
843
844 bool dop1ava = false;
845 bool dop2ava = false;
846 bool ignore = false;
847 bool smoothMesh = false;
848
849 switch (p1.PhysicsActorType)
850 {
851 case (int)ActorTypes.Agent:
852 {
853 dop1ava = true;
854 switch (p2.PhysicsActorType)
855 {
856 case (int)ActorTypes.Agent:
857 case (int)ActorTypes.Prim:
858 break;
859
860 default:
861 ignore = true; // avatar to terrain and water ignored
862 break;
863 }
864 break;
865 }
866
867 case (int)ActorTypes.Prim:
868 {
869 switch (p2.PhysicsActorType)
870 {
871 case (int)ActorTypes.Agent:
872 dop2ava = true;
873 break;
874
875 case (int)ActorTypes.Prim:
876 Vector3 relV = p1.Velocity - p2.Velocity;
877 float relVlenSQ = relV.LengthSquared();
878 if (relVlenSQ > 0.0001f)
879 {
880 p1.CollidingObj = true;
881 p2.CollidingObj = true;
882 }
883 p1.getContactData(ref contactdata1);
884 p2.getContactData(ref contactdata2);
885 bounce = contactdata1.bounce * contactdata2.bounce;
886 mu = (float)Math.Sqrt(contactdata1.mu * contactdata2.mu);
887
888 if (relVlenSQ > 0.01f)
889 mu *= frictionMovementMult;
890
891 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass &&
892 d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
893 smoothMesh = true;
894 break;
895
896 case (int)ActorTypes.Ground:
897 p1.getContactData(ref contactdata1);
898 bounce = contactdata1.bounce * TerrainBounce;
899 mu = (float)Math.Sqrt(contactdata1.mu * TerrainFriction);
900
901 if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f)
902 mu *= frictionMovementMult;
903 p1.CollidingGround = true;
904
905 if(d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass)
906 smoothMesh = true;
907 break;
908
909 case (int)ActorTypes.Water:
910 default:
911 ignore = true;
912 break;
913 }
914 }
915 break;
916
917 case (int)ActorTypes.Ground:
918 if (p2.PhysicsActorType == (int)ActorTypes.Prim)
919 {
920 p2.CollidingGround = true;
921 p2.getContactData(ref contactdata2);
922 bounce = contactdata2.bounce * TerrainBounce;
923 mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction);
924
925// if (curContact.side1 > 0) // should be 2 ?
926// IgnoreNegSides = true;
927
928 if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f)
929 mu *= frictionMovementMult;
930
931 if(d.GeomGetClass(g2) == d.GeomClassID.TriMeshClass)
932 smoothMesh = true;
933 }
934 else
935 ignore = true;
936 break;
937
938 case (int)ActorTypes.Water:
939 default:
940 break;
941 }
942
943 if (ignore)
944 return;
945
946 IntPtr Joint;
947 bool FeetCollision = false;
948 int ncontacts = 0;
949
950 int i = 0;
951
952 maxDepthContact = new ContactPoint();
953 maxDepthContact.PenetrationDepth = float.MinValue;
954 ContactPoint minDepthContact = new ContactPoint();
955 minDepthContact.PenetrationDepth = float.MaxValue;
956
957 SharedTmpcontact.geom.depth = 0;
958 SharedTmpcontact.surface.mu = mu;
959 SharedTmpcontact.surface.bounce = bounce;
960
961 d.ContactGeom altContact = new d.ContactGeom();
962 bool useAltcontact = false;
963 bool noskip = true;
964
965 if(dop1ava || dop2ava)
966 smoothMesh = false;
967
968 while (true)
969 {
970 noskip = true;
971 useAltcontact = false;
972
973 if (dop1ava)
974 {
975 if ((((OdeCharacter)p1).Collide(g1, g2, false, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
976 {
977 if (p2.PhysicsActorType == (int)ActorTypes.Agent)
978 {
979 p1.CollidingObj = true;
980 p2.CollidingObj = true;
981 }
982 else if (p2.Velocity.LengthSquared() > 0.0f)
983 p2.CollidingObj = true;
984 }
985 else
986 noskip = false;
987 }
988 else if (dop2ava)
989 {
990 if ((((OdeCharacter)p2).Collide(g2, g1, true, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
991 {
992 if (p1.PhysicsActorType == (int)ActorTypes.Agent)
993 {
994 p1.CollidingObj = true;
995 p2.CollidingObj = true;
996 }
997 else if (p2.Velocity.LengthSquared() > 0.0f)
998 p1.CollidingObj = true;
999 }
1000 else
1001 noskip = false;
1002 }
1003
1004 if (noskip)
1005 {
1006 if(useAltcontact)
1007 Joint = CreateContacJoint(ref altContact,smoothMesh);
1008 else
1009 Joint = CreateContacJoint(ref curContact,smoothMesh);
1010
1011 if (Joint == IntPtr.Zero)
1012 break;
1013
1014 d.JointAttach(Joint, b1, b2);
1015
1016 ncontacts++;
1017
1018 if (curContact.depth > maxDepthContact.PenetrationDepth)
1019 {
1020 maxDepthContact.Position.X = curContact.pos.X;
1021 maxDepthContact.Position.Y = curContact.pos.Y;
1022 maxDepthContact.Position.Z = curContact.pos.Z;
1023 maxDepthContact.PenetrationDepth = curContact.depth;
1024 maxDepthContact.CharacterFeet = FeetCollision;
1025 }
1026
1027 if (curContact.depth < minDepthContact.PenetrationDepth)
1028 {
1029 minDepthContact.PenetrationDepth = curContact.depth;
1030 minDepthContact.SurfaceNormal.X = curContact.normal.X;
1031 minDepthContact.SurfaceNormal.Y = curContact.normal.Y;
1032 minDepthContact.SurfaceNormal.Z = curContact.normal.Z;
1033 }
1034 }
1035
1036 if (++i >= count)
1037 break;
1038
1039 if (!GetCurContactGeom(i, ref curContact))
1040 break;
1041 }
1042
1043 if (ncontacts > 0)
1044 {
1045 maxDepthContact.SurfaceNormal.X = minDepthContact.SurfaceNormal.X;
1046 maxDepthContact.SurfaceNormal.Y = minDepthContact.SurfaceNormal.Y;
1047 maxDepthContact.SurfaceNormal.Z = minDepthContact.SurfaceNormal.Z;
1048
1049 collision_accounting_events(p1, p2, maxDepthContact);
1050 }
1051 }
1052
1053 private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact)
1054 {
1055 uint obj2LocalID = 0;
1056
1057 bool p1events = p1.SubscribedEvents();
1058 bool p2events = p2.SubscribedEvents();
1059
1060 if (p1.IsVolumeDtc)
1061 p2events = false;
1062 if (p2.IsVolumeDtc)
1063 p1events = false;
1064
1065 if (!p2events && !p1events)
1066 return;
1067
1068 Vector3 vel = Vector3.Zero;
1069 if (p2 != null && p2.IsPhysical)
1070 vel = p2.Velocity;
1071
1072 if (p1 != null && p1.IsPhysical)
1073 vel -= p1.Velocity;
1074
1075 contact.RelativeSpeed = Vector3.Dot(vel, contact.SurfaceNormal);
1076
1077 switch ((ActorTypes)p1.PhysicsActorType)
1078 {
1079 case ActorTypes.Agent:
1080 case ActorTypes.Prim:
1081 {
1082 switch ((ActorTypes)p2.PhysicsActorType)
1083 {
1084 case ActorTypes.Agent:
1085 case ActorTypes.Prim:
1086 if (p2events)
1087 {
1088 AddCollisionEventReporting(p2);
1089 p2.AddCollisionEvent(p1.ParentActor.LocalID, contact);
1090 }
1091 obj2LocalID = p2.ParentActor.LocalID;
1092 break;
1093
1094 case ActorTypes.Ground:
1095 case ActorTypes.Unknown:
1096 default:
1097 obj2LocalID = 0;
1098 break;
1099 }
1100 if (p1events)
1101 {
1102 contact.SurfaceNormal = -contact.SurfaceNormal;
1103 AddCollisionEventReporting(p1);
1104 p1.AddCollisionEvent(obj2LocalID, contact);
1105 }
1106 break;
1107 }
1108 case ActorTypes.Ground:
1109 case ActorTypes.Unknown:
1110 default:
1111 {
1112 if (p2events && !p2.IsVolumeDtc)
1113 {
1114 AddCollisionEventReporting(p2);
1115 p2.AddCollisionEvent(0, contact);
1116 }
1117 break;
1118 }
1119 }
1120 }
1121
1122 /// <summary>
1123 /// This is our collision testing routine in ODE
1124 /// </summary>
1125 /// <param name="timeStep"></param>
1126 private void collision_optimized()
1127 {
1128 lock (_characters)
1129 {
1130 try
1131 {
1132 foreach (OdeCharacter chr in _characters)
1133 {
1134 if (chr == null)
1135 continue;
1136
1137 chr.IsColliding = false;
1138 // chr.CollidingGround = false; not done here
1139 chr.CollidingObj = false;
1140
1141 if(chr.Body == IntPtr.Zero || chr.collider == IntPtr.Zero )
1142 continue;
1143
1144 // do colisions with static space
1145 d.SpaceCollide2(chr.collider, StaticSpace, IntPtr.Zero, nearCallback);
1146
1147 // no coll with gnd
1148 }
1149 // chars with chars
1150 d.SpaceCollide(CharsSpace, IntPtr.Zero, nearCallback);
1151
1152 }
1153 catch (AccessViolationException)
1154 {
1155 m_log.Warn("[PHYSICS]: Unable to collide Character to static space");
1156 }
1157
1158 }
1159
1160 lock (_activeprims)
1161 {
1162 foreach (OdePrim aprim in _activeprims)
1163 {
1164 aprim.CollisionScore = 0;
1165 aprim.IsColliding = false;
1166 }
1167 }
1168 lock (_activegroups)
1169 {
1170 try
1171 {
1172 foreach (OdePrim aprim in _activegroups)
1173 {
1174 if(!aprim.m_outbounds && d.BodyIsEnabled(aprim.Body) &&
1175 aprim.collide_geom != IntPtr.Zero)
1176 {
1177 d.SpaceCollide2(StaticSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1178 d.SpaceCollide2(GroundSpace, aprim.collide_geom, IntPtr.Zero, nearCallback);
1179 }
1180 }
1181 }
1182 catch (Exception e)
1183 {
1184 m_log.Warn("[PHYSICS]: Unable to collide Active to Static: " + e.Message);
1185 }
1186 }
1187
1188 // colide active amoung them
1189 try
1190 {
1191 d.SpaceCollide(ActiveSpace, IntPtr.Zero, nearCallback);
1192 }
1193 catch (Exception e)
1194 {
1195 m_log.Warn("[PHYSICS]: Unable to collide in Active: " + e.Message);
1196 }
1197
1198 // and with chars
1199 try
1200 {
1201 d.SpaceCollide2(CharsSpace,ActiveSpace, IntPtr.Zero, nearCallback);
1202 }
1203 catch (Exception e)
1204 {
1205 m_log.Warn("[PHYSICS]: Unable to collide Active to Character: " + e.Message);
1206 }
1207 }
1208
1209 #endregion
1210 /// <summary>
1211 /// Add actor to the list that should receive collision events in the simulate loop.
1212 /// </summary>
1213 /// <param name="obj"></param>
1214 public void AddCollisionEventReporting(PhysicsActor obj)
1215 {
1216 if (!_collisionEventPrim.Contains(obj))
1217 _collisionEventPrim.Add(obj);
1218 }
1219
1220 /// <summary>
1221 /// Remove actor from the list that should receive collision events in the simulate loop.
1222 /// </summary>
1223 /// <param name="obj"></param>
1224 public void RemoveCollisionEventReporting(PhysicsActor obj)
1225 {
1226 if (_collisionEventPrim.Contains(obj) && !_collisionEventPrimRemove.Contains(obj))
1227 _collisionEventPrimRemove.Add(obj);
1228 }
1229
1230 public override float TimeDilation
1231 {
1232 get { return m_timeDilation; }
1233 }
1234
1235 public override bool SupportsNINJAJoints
1236 {
1237 get { return false; }
1238 }
1239
1240 #region Add/Remove Entities
1241
1242 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 velocity, Vector3 size, bool isFlying)
1243 {
1244 return null;
1245 }
1246
1247 public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, float feetOffset, bool isFlying)
1248 {
1249 OdeCharacter newAv = new OdeCharacter(localID, avName, this, position,
1250 size, feetOffset, avDensity, avMovementDivisorWalk, avMovementDivisorRun);
1251 newAv.Flying = isFlying;
1252 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1253
1254 return newAv;
1255 }
1256
1257 public void AddCharacter(OdeCharacter chr)
1258 {
1259 lock (_characters)
1260 {
1261 if (!_characters.Contains(chr))
1262 {
1263 _characters.Add(chr);
1264 if (chr.bad)
1265 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1266 }
1267 }
1268 }
1269
1270 public void RemoveCharacter(OdeCharacter chr)
1271 {
1272 lock (_characters)
1273 {
1274 if (_characters.Contains(chr))
1275 {
1276 _characters.Remove(chr);
1277 }
1278 }
1279 }
1280
1281 public void BadCharacter(OdeCharacter chr)
1282 {
1283 lock (_badCharacter)
1284 {
1285 if (!_badCharacter.Contains(chr))
1286 _badCharacter.Add(chr);
1287 }
1288 }
1289
1290 public override void RemoveAvatar(PhysicsActor actor)
1291 {
1292 //m_log.Debug("[PHYSICS]:ODELOCK");
1293 ((OdeCharacter) actor).Destroy();
1294 }
1295
1296
1297 public void addActivePrim(OdePrim activatePrim)
1298 {
1299 // adds active prim..
1300 lock (_activeprims)
1301 {
1302 if (!_activeprims.Contains(activatePrim))
1303 _activeprims.Add(activatePrim);
1304 }
1305 }
1306
1307 public void addActiveGroups(OdePrim activatePrim)
1308 {
1309 lock (_activegroups)
1310 {
1311 if (!_activegroups.Contains(activatePrim))
1312 _activegroups.Add(activatePrim);
1313 }
1314 }
1315
1316 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1317 PrimitiveBaseShape pbs, bool isphysical, bool isPhantom, byte shapeType, uint localID)
1318 {
1319 OdePrim newPrim;
1320 lock (OdeLock)
1321 {
1322 newPrim = new OdePrim(name, this, position, size, rotation, pbs, isphysical, isPhantom, shapeType, localID);
1323 lock (_prims)
1324 _prims.Add(newPrim);
1325 }
1326 return newPrim;
1327 }
1328
1329 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1330 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, uint localid)
1331 {
1332 return AddPrim(primName, position, size, rotation, pbs, isPhysical, isPhantom, 0 , localid);
1333 }
1334
1335
1336 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1337 Vector3 size, Quaternion rotation, bool isPhysical, uint localid)
1338 {
1339 return AddPrim(primName, position, size, rotation, pbs, isPhysical,false, 0, localid);
1340 }
1341
1342 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
1343 Vector3 size, Quaternion rotation, bool isPhysical, bool isPhantom, byte shapeType, uint localid)
1344 {
1345
1346 return AddPrim(primName, position, size, rotation, pbs, isPhysical,isPhantom, shapeType, localid);
1347 }
1348
1349 public void remActivePrim(OdePrim deactivatePrim)
1350 {
1351 lock (_activeprims)
1352 {
1353 _activeprims.Remove(deactivatePrim);
1354 }
1355 }
1356 public void remActiveGroup(OdePrim deactivatePrim)
1357 {
1358 lock (_activegroups)
1359 {
1360 _activegroups.Remove(deactivatePrim);
1361 }
1362 }
1363
1364 public override void RemovePrim(PhysicsActor prim)
1365 {
1366 // As with all ODE physics operations, we don't remove the prim immediately but signal that it should be
1367 // removed in the next physics simulate pass.
1368 if (prim is OdePrim)
1369 {
1370// lock (OdeLock)
1371 {
1372
1373 OdePrim p = (OdePrim)prim;
1374 p.setPrimForRemoval();
1375 }
1376 }
1377 }
1378
1379 public void RemovePrimThreadLocked(OdePrim prim)
1380 {
1381 //Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
1382 lock (prim)
1383 {
1384// RemoveCollisionEventReporting(prim);
1385 lock (_prims)
1386 _prims.Remove(prim);
1387 }
1388
1389 }
1390
1391 public bool havePrim(OdePrim prm)
1392 {
1393 lock (_prims)
1394 return _prims.Contains(prm);
1395 }
1396
1397 public bool haveActor(PhysicsActor actor)
1398 {
1399 if (actor is OdePrim)
1400 {
1401 lock (_prims)
1402 return _prims.Contains((OdePrim)actor);
1403 }
1404 else if (actor is OdeCharacter)
1405 {
1406 lock (_characters)
1407 return _characters.Contains((OdeCharacter)actor);
1408 }
1409 return false;
1410 }
1411
1412 #endregion
1413
1414 #region Space Separation Calculation
1415
1416 /// <summary>
1417 /// Called when a static prim moves or becomes static
1418 /// Places the prim in a space one the static sub-spaces grid
1419 /// </summary>
1420 /// <param name="geom">the pointer to the geom that moved</param>
1421 /// <param name="pos">the position that the geom moved to</param>
1422 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
1423 /// <returns>a pointer to the new space it's in</returns>
1424 public IntPtr MoveGeomToStaticSpace(IntPtr geom, Vector3 pos, IntPtr currentspace)
1425 {
1426 // moves a prim into another static sub-space or from another space into a static sub-space
1427
1428 // Called ODEPrim so
1429 // it's already in locked space.
1430
1431 if (geom == IntPtr.Zero) // shouldn't happen
1432 return IntPtr.Zero;
1433
1434 // get the static sub-space for current position
1435 IntPtr newspace = calculateSpaceForGeom(pos);
1436
1437 if (newspace == currentspace) // if we are there all done
1438 return newspace;
1439
1440 // else remove it from its current space
1441 if (currentspace != IntPtr.Zero && d.SpaceQuery(currentspace, geom))
1442 {
1443 if (d.GeomIsSpace(currentspace))
1444 {
1445 waitForSpaceUnlock(currentspace);
1446 d.SpaceRemove(currentspace, geom);
1447
1448 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1449 {
1450 d.SpaceDestroy(currentspace);
1451 }
1452 }
1453 else
1454 {
1455 m_log.Info("[Physics]: Invalid or empty Space passed to 'MoveGeomToStaticSpace':" + currentspace +
1456 " Geom:" + geom);
1457 }
1458 }
1459 else // odd currentspace is null or doesn't contain the geom? lets try the geom ideia of current space
1460 {
1461 currentspace = d.GeomGetSpace(geom);
1462 if (currentspace != IntPtr.Zero)
1463 {
1464 if (d.GeomIsSpace(currentspace))
1465 {
1466 waitForSpaceUnlock(currentspace);
1467 d.SpaceRemove(currentspace, geom);
1468
1469 if (d.SpaceGetSublevel(currentspace) > 2 && d.SpaceGetNumGeoms(currentspace) == 0)
1470 {
1471 d.SpaceDestroy(currentspace);
1472 }
1473
1474 }
1475 }
1476 }
1477
1478 // put the geom in the newspace
1479 waitForSpaceUnlock(newspace);
1480 d.SpaceAdd(newspace, geom);
1481
1482 // let caller know this newspace
1483 return newspace;
1484 }
1485
1486 /// <summary>
1487 /// Calculates the space the prim should be in by its position
1488 /// </summary>
1489 /// <param name="pos"></param>
1490 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
1491 public IntPtr calculateSpaceForGeom(Vector3 pos)
1492 {
1493 int x, y;
1494
1495 if (pos.X < 0)
1496 return staticPrimspaceOffRegion[0];
1497
1498 if (pos.Y < 0)
1499 return staticPrimspaceOffRegion[2];
1500
1501 x = (int)(pos.X * spacesPerMeterX);
1502 if (x > spaceGridMaxX)
1503 return staticPrimspaceOffRegion[1];
1504
1505 y = (int)(pos.Y * spacesPerMeterY);
1506 if (y > spaceGridMaxY)
1507 return staticPrimspaceOffRegion[3];
1508
1509 return staticPrimspace[x, y];
1510 }
1511
1512 #endregion
1513
1514
1515 /// <summary>
1516 /// Called to queue a change to a actor
1517 /// to use in place of old taint mechanism so changes do have a time sequence
1518 /// </summary>
1519
1520 public void AddChange(PhysicsActor actor, changes what, Object arg)
1521 {
1522 ODEchangeitem item = new ODEchangeitem();
1523 item.actor = actor;
1524 item.what = what;
1525 item.arg = arg;
1526 ChangesQueue.Enqueue(item);
1527 }
1528
1529 /// <summary>
1530 /// Called after our prim properties are set Scale, position etc.
1531 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
1532 /// This assures us that we have no race conditions
1533 /// </summary>
1534 /// <param name="prim"></param>
1535 public override void AddPhysicsActorTaint(PhysicsActor prim)
1536 {
1537 }
1538
1539 // does all pending changes generated during region load process
1540 public override void ProcessPreSimulation()
1541 {
1542 lock (OdeLock)
1543 {
1544 if (world == IntPtr.Zero)
1545 {
1546 ChangesQueue.Clear();
1547 return;
1548 }
1549
1550 ODEchangeitem item;
1551
1552 int donechanges = 0;
1553 if (ChangesQueue.Count > 0)
1554 {
1555 m_log.InfoFormat("[ubOde] start processing pending actor operations");
1556 int tstart = Util.EnvironmentTickCount();
1557
1558 while (ChangesQueue.Dequeue(out item))
1559 {
1560 if (item.actor != null)
1561 {
1562 try
1563 {
1564 if (item.actor is OdeCharacter)
1565 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1566 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1567 RemovePrimThreadLocked((OdePrim)item.actor);
1568 }
1569 catch
1570 {
1571 m_log.WarnFormat("[PHYSICS]: Operation failed for a actor {0} {1}",
1572 item.actor.Name, item.what.ToString());
1573 }
1574 }
1575 donechanges++;
1576 }
1577 int time = Util.EnvironmentTickCountSubtract(tstart);
1578 m_log.InfoFormat("[ubOde] finished {0} operations in {1}ms", donechanges, time);
1579 }
1580 m_log.InfoFormat("[ubOde] {0} prim actors loaded",_prims.Count);
1581 }
1582 }
1583
1584 /// <summary>
1585 /// This is our main simulate loop
1586 /// It's thread locked by a Mutex in the scene.
1587 /// It holds Collisions, it instructs ODE to step through the physical reactions
1588 /// It moves the objects around in memory
1589 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
1590 /// </summary>
1591 /// <param name="timeStep"></param>
1592 /// <returns></returns>
1593 public override float Simulate(float reqTimeStep)
1594 {
1595 DateTime now = DateTime.UtcNow;
1596 TimeSpan timedif = now - m_lastframe;
1597 float timeStep = (float)timedif.TotalSeconds;
1598 m_lastframe = now;
1599
1600 // acumulate time so we can reduce error
1601 step_time += timeStep;
1602
1603 if (step_time < HalfOdeStep)
1604 return 0;
1605
1606 if (framecount < 0)
1607 framecount = 0;
1608
1609 framecount++;
1610
1611// checkThread();
1612 int nodeframes = 0;
1613 float fps = 0;
1614
1615 lock (SimulationLock)
1616 lock(OdeLock)
1617 {
1618 if (world == IntPtr.Zero)
1619 {
1620 ChangesQueue.Clear();
1621 return 0;
1622 }
1623
1624 ODEchangeitem item;
1625
1626// d.WorldSetQuickStepNumIterations(world, curphysiteractions);
1627
1628 int loopstartMS = Util.EnvironmentTickCount();
1629 int looptimeMS = 0;
1630 int changestimeMS = 0;
1631 int maxChangestime = (int)(reqTimeStep * 500f); // half the time
1632 int maxLoopTime = (int)(reqTimeStep * 1200f); // 1.2 the time
1633
1634 if (ChangesQueue.Count > 0)
1635 {
1636 while (ChangesQueue.Dequeue(out item))
1637 {
1638 if (item.actor != null)
1639 {
1640 try
1641 {
1642 if (item.actor is OdeCharacter)
1643 ((OdeCharacter)item.actor).DoAChange(item.what, item.arg);
1644 else if (((OdePrim)item.actor).DoAChange(item.what, item.arg))
1645 RemovePrimThreadLocked((OdePrim)item.actor);
1646 }
1647 catch
1648 {
1649 m_log.WarnFormat("[PHYSICS]: doChange failed for a actor {0} {1}",
1650 item.actor.Name, item.what.ToString());
1651 }
1652 }
1653 changestimeMS = Util.EnvironmentTickCountSubtract(loopstartMS);
1654 if (changestimeMS > maxChangestime)
1655 break;
1656 }
1657 }
1658
1659 // do simulation taking at most 150ms total time including changes
1660 while (step_time > HalfOdeStep)
1661 {
1662 try
1663 {
1664 // clear pointer/counter to contacts to pass into joints
1665 m_global_contactcount = 0;
1666
1667
1668 // Move characters
1669 lock (_characters)
1670 {
1671 List<OdeCharacter> defects = new List<OdeCharacter>();
1672 foreach (OdeCharacter actor in _characters)
1673 {
1674 if (actor != null)
1675 actor.Move(defects);
1676 }
1677 if (defects.Count != 0)
1678 {
1679 foreach (OdeCharacter defect in defects)
1680 {
1681 RemoveCharacter(defect);
1682 }
1683 defects.Clear();
1684 }
1685 }
1686
1687 // Move other active objects
1688 lock (_activegroups)
1689 {
1690 foreach (OdePrim aprim in _activegroups)
1691 {
1692 aprim.Move();
1693 }
1694 }
1695
1696 m_rayCastManager.ProcessQueuedRequests();
1697
1698 collision_optimized();
1699
1700 foreach (PhysicsActor obj in _collisionEventPrim)
1701 {
1702 if (obj == null)
1703 continue;
1704
1705 switch ((ActorTypes)obj.PhysicsActorType)
1706 {
1707 case ActorTypes.Agent:
1708 OdeCharacter cobj = (OdeCharacter)obj;
1709 cobj.AddCollisionFrameTime((int)(odetimestepMS));
1710 cobj.SendCollisions();
1711 break;
1712
1713 case ActorTypes.Prim:
1714 OdePrim pobj = (OdePrim)obj;
1715 if (pobj.Body == IntPtr.Zero || (d.BodyIsEnabled(pobj.Body) && !pobj.m_outbounds))
1716 if (!pobj.m_outbounds)
1717 {
1718 pobj.AddCollisionFrameTime((int)(odetimestepMS));
1719 pobj.SendCollisions();
1720 }
1721 break;
1722 }
1723 }
1724
1725 foreach (PhysicsActor obj in _collisionEventPrimRemove)
1726 _collisionEventPrim.Remove(obj);
1727
1728 _collisionEventPrimRemove.Clear();
1729
1730 // do a ode simulation step
1731 d.WorldQuickStep(world, ODE_STEPSIZE);
1732 d.JointGroupEmpty(contactgroup);
1733
1734 // update managed ideia of physical data and do updates to core
1735 /*
1736 lock (_characters)
1737 {
1738 foreach (OdeCharacter actor in _characters)
1739 {
1740 if (actor != null)
1741 {
1742 if (actor.bad)
1743 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
1744
1745 actor.UpdatePositionAndVelocity();
1746 }
1747 }
1748 }
1749 */
1750
1751 lock (_activegroups)
1752 {
1753 {
1754 foreach (OdePrim actor in _activegroups)
1755 {
1756 if (actor.IsPhysical)
1757 {
1758 actor.UpdatePositionAndVelocity(framecount);
1759 }
1760 }
1761 }
1762 }
1763 }
1764 catch (Exception e)
1765 {
1766 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
1767// ode.dunlock(world);
1768 }
1769
1770 step_time -= ODE_STEPSIZE;
1771 nodeframes++;
1772
1773 looptimeMS = Util.EnvironmentTickCountSubtract(loopstartMS);
1774 if (looptimeMS > maxLoopTime)
1775 break;
1776 }
1777
1778 lock (_badCharacter)
1779 {
1780 if (_badCharacter.Count > 0)
1781 {
1782 foreach (OdeCharacter chr in _badCharacter)
1783 {
1784 RemoveCharacter(chr);
1785 }
1786
1787 _badCharacter.Clear();
1788 }
1789 }
1790
1791 timedif = now - m_lastMeshExpire;
1792
1793 if (timedif.Seconds > 10)
1794 {
1795 mesher.ExpireReleaseMeshs();
1796 m_lastMeshExpire = now;
1797 }
1798
1799// information block for in debug breakpoint only
1800/*
1801 int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
1802 int ntopstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
1803 int ngroundgeoms = d.SpaceGetNumGeoms(GroundSpace);
1804
1805 int nactivegeoms = 0;
1806 int nactivespaces = 0;
1807
1808 int nstaticgeoms = 0;
1809 int nstaticspaces = 0;
1810 IntPtr sp;
1811
1812 for (int i = 0; i < ntopactivegeoms; i++)
1813 {
1814 sp = d.SpaceGetGeom(ActiveSpace, i);
1815 if (d.GeomIsSpace(sp))
1816 {
1817 nactivespaces++;
1818 nactivegeoms += d.SpaceGetNumGeoms(sp);
1819 }
1820 else
1821 nactivegeoms++;
1822 }
1823
1824 for (int i = 0; i < ntopstaticgeoms; i++)
1825 {
1826 sp = d.SpaceGetGeom(StaticSpace, i);
1827 if (d.GeomIsSpace(sp))
1828 {
1829 nstaticspaces++;
1830 nstaticgeoms += d.SpaceGetNumGeoms(sp);
1831 }
1832 else
1833 nstaticgeoms++;
1834 }
1835
1836 int ntopgeoms = d.SpaceGetNumGeoms(TopSpace);
1837
1838 int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray
1839 int nbodies = d.NTotalBodies;
1840 int ngeoms = d.NTotalGeoms;
1841*/
1842 // Finished with all sim stepping. If requested, dump world state to file for debugging.
1843 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
1844 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
1845 if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0))
1846 {
1847 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
1848 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
1849
1850 if (physics_logging_append_existing_logfile)
1851 {
1852 string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------";
1853 TextWriter fwriter = File.AppendText(fname);
1854 fwriter.WriteLine(header);
1855 fwriter.Close();
1856 }
1857
1858 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
1859 }
1860
1861 fps = (float)nodeframes * ODE_STEPSIZE / reqTimeStep;
1862
1863 if(step_time < HalfOdeStep)
1864 m_timeDilation = 1.0f;
1865 else if (step_time > m_SkipFramesAtms)
1866 {
1867 // if we lag too much skip frames
1868 m_timeDilation = 0.0f;
1869 step_time = 0;
1870 m_lastframe = DateTime.UtcNow; // skip also the time lost
1871 }
1872 else
1873 {
1874 m_timeDilation = ODE_STEPSIZE / step_time;
1875 if (m_timeDilation > 1)
1876 m_timeDilation = 1;
1877 }
1878 }
1879
1880 return fps;
1881 }
1882
1883 /// <summary>
1884 public override void GetResults()
1885 {
1886 }
1887
1888 public override bool IsThreaded
1889 {
1890 // for now we won't be multithreaded
1891 get { return (false); }
1892 }
1893
1894 public float GetTerrainHeightAtXY(float x, float y)
1895 {
1896
1897 int offsetX = 0;
1898 int offsetY = 0;
1899
1900 if (m_suportCombine)
1901 {
1902 offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1903 offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
1904 }
1905
1906 // get region map
1907 IntPtr heightFieldGeom = IntPtr.Zero;
1908 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
1909 return 0f;
1910
1911 if (heightFieldGeom == IntPtr.Zero)
1912 return 0f;
1913
1914 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
1915 return 0f;
1916
1917 // TerrainHeightField for ODE as offset 1m
1918 x += 1f - offsetX;
1919 y += 1f - offsetY;
1920
1921 // make position fit into array
1922 if (x < 0)
1923 x = 0;
1924 if (y < 0)
1925 y = 0;
1926
1927 // integer indexs
1928 int ix;
1929 int iy;
1930 // interpolators offset
1931 float dx;
1932 float dy;
1933
1934 int regsizeX = (int)m_regionWidth + 3; // map size see setterrain number of samples
1935 int regsizeY = (int)m_regionHeight + 3; // map size see setterrain number of samples
1936 int regsize = regsizeX;
1937
1938 if (m_OSOdeLib)
1939 {
1940 if (x < regsizeX - 1)
1941 {
1942 ix = (int)x;
1943 dx = x - (float)ix;
1944 }
1945 else // out world use external height
1946 {
1947 ix = regsizeX - 2;
1948 dx = 0;
1949 }
1950 if (y < regsizeY - 1)
1951 {
1952 iy = (int)y;
1953 dy = y - (float)iy;
1954 }
1955 else
1956 {
1957 iy = regsizeY - 2;
1958 dy = 0;
1959 }
1960 }
1961 else
1962 {
1963 // we still have square fixed size regions
1964 // also flip x and y because of how map is done for ODE fliped axis
1965 // so ix,iy,dx and dy are inter exchanged
1966
1967 regsize = regsizeY;
1968
1969 if (x < regsizeX - 1)
1970 {
1971 iy = (int)x;
1972 dy = x - (float)iy;
1973 }
1974 else // out world use external height
1975 {
1976 iy = regsizeX - 2;
1977 dy = 0;
1978 }
1979 if (y < regsizeY - 1)
1980 {
1981 ix = (int)y;
1982 dx = y - (float)ix;
1983 }
1984 else
1985 {
1986 ix = regsizeY - 2;
1987 dx = 0;
1988 }
1989 }
1990
1991 float h0;
1992 float h1;
1993 float h2;
1994
1995 iy *= regsize;
1996 iy += ix; // all indexes have iy + ix
1997
1998 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
1999 /*
2000 if ((dx + dy) <= 1.0f)
2001 {
2002 h0 = ((float)heights[iy]); // 0,0 vertice
2003 h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0
2004 h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0
2005 }
2006 else
2007 {
2008 h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice
2009 h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0
2010 h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1
2011 }
2012 */
2013 h0 = ((float)heights[iy]); // 0,0 vertice
2014
2015 if (dy>dx)
2016 {
2017 iy += regsize;
2018 h2 = (float)heights[iy]; // 0,1 vertice
2019 h1 = (h2 - h0) * dy; // 0,1 vertice minus 0,0
2020 h2 = ((float)heights[iy + 1] - h2) * dx; // 1,1 vertice minus 0,1
2021 }
2022 else
2023 {
2024 iy++;
2025 h2 = (float)heights[iy]; // vertice 1,0
2026 h1 = (h2 - h0) * dx; // 1,0 vertice minus 0,0
2027 h2 = (((float)heights[iy + regsize]) - h2) * dy; // 1,1 vertice minus 1,0
2028 }
2029
2030 return h0 + h1 + h2;
2031 }
2032
2033 public Vector3 GetTerrainNormalAtXY(float x, float y)
2034 {
2035 int offsetX = 0;
2036 int offsetY = 0;
2037
2038 if (m_suportCombine)
2039 {
2040 offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2041 offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
2042 }
2043
2044 // get region map
2045 IntPtr heightFieldGeom = IntPtr.Zero;
2046 Vector3 norm = new Vector3(0, 0, 1);
2047
2048 if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
2049 return norm; ;
2050
2051 if (heightFieldGeom == IntPtr.Zero)
2052 return norm;
2053
2054 if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
2055 return norm;
2056
2057 // TerrainHeightField for ODE as offset 1m
2058 x += 1f - offsetX;
2059 y += 1f - offsetY;
2060
2061 // make position fit into array
2062 if (x < 0)
2063 x = 0;
2064 if (y < 0)
2065 y = 0;
2066
2067 // integer indexs
2068 int ix;
2069 int iy;
2070 // interpolators offset
2071 float dx;
2072 float dy;
2073
2074 int regsizeX = (int)m_regionWidth + 3; // map size see setterrain number of samples
2075 int regsizeY = (int)m_regionHeight + 3; // map size see setterrain number of samples
2076 int regsize = regsizeX;
2077
2078 int xstep = 1;
2079 int ystep = regsizeX;
2080 bool firstTri = false;
2081
2082 if (m_OSOdeLib)
2083 {
2084 if (x < regsizeX - 1)
2085 {
2086 ix = (int)x;
2087 dx = x - (float)ix;
2088 }
2089 else // out world use external height
2090 {
2091 ix = regsizeX - 2;
2092 dx = 0;
2093 }
2094 if (y < regsizeY - 1)
2095 {
2096 iy = (int)y;
2097 dy = y - (float)iy;
2098 }
2099 else
2100 {
2101 iy = regsizeY - 2;
2102 dy = 0;
2103 }
2104 firstTri = dy > dx;
2105 }
2106
2107 else
2108 {
2109 xstep = regsizeY;
2110 ystep = 1;
2111 regsize = regsizeY;
2112
2113 // we still have square fixed size regions
2114 // also flip x and y because of how map is done for ODE fliped axis
2115 // so ix,iy,dx and dy are inter exchanged
2116 if (x < regsizeX - 1)
2117 {
2118 iy = (int)x;
2119 dy = x - (float)iy;
2120 }
2121 else // out world use external height
2122 {
2123 iy = regsizeX - 2;
2124 dy = 0;
2125 }
2126 if (y < regsizeY - 1)
2127 {
2128 ix = (int)y;
2129 dx = y - (float)ix;
2130 }
2131 else
2132 {
2133 ix = regsizeY - 2;
2134 dx = 0;
2135 }
2136 firstTri = dx > dy;
2137 }
2138
2139 float h0;
2140 float h1;
2141 float h2;
2142
2143 iy *= regsize;
2144 iy += ix; // all indexes have iy + ix
2145
2146 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
2147
2148 if (firstTri)
2149 {
2150 h1 = ((float)heights[iy]); // 0,0 vertice
2151 iy += ystep;
2152 h0 = (float)heights[iy]; // 0,1
2153 h2 = (float)heights[iy+xstep]; // 1,1 vertice
2154 norm.X = h0 - h2;
2155 norm.Y = h1 - h0;
2156 }
2157 else
2158 {
2159 h2 = ((float)heights[iy]); // 0,0 vertice
2160 iy += xstep;
2161 h0 = ((float)heights[iy]); // 1,0 vertice
2162 h1 = (float)heights[iy+ystep]; // vertice 1,1
2163 norm.X = h2 - h0;
2164 norm.Y = h0 - h1;
2165 }
2166 norm.Z = 1;
2167 norm.Normalize();
2168 return norm;
2169 }
2170
2171 public override void SetTerrain(float[] heightMap)
2172 {
2173 if (m_worldOffset != Vector3.Zero && m_parentScene != null)
2174 {
2175 if (m_parentScene is ODEScene)
2176 {
2177 ((ODEScene)m_parentScene).SetTerrain(heightMap, m_worldOffset);
2178 }
2179 }
2180 else
2181 {
2182 SetTerrain(heightMap, m_worldOffset);
2183 }
2184 }
2185
2186 public override void CombineTerrain(float[] heightMap, Vector3 pOffset)
2187 {
2188 if(m_suportCombine)
2189 SetTerrain(heightMap, pOffset);
2190 }
2191
2192 public void SetTerrain(float[] heightMap, Vector3 pOffset)
2193 {
2194 if (m_OSOdeLib)
2195 OSSetTerrain(heightMap, pOffset);
2196 else
2197 OriSetTerrain(heightMap, pOffset);
2198 }
2199
2200 public void OriSetTerrain(float[] heightMap, Vector3 pOffset)
2201 {
2202 // assumes 1m size grid and constante size square regions
2203 // needs to know about sims around in future
2204
2205 float[] _heightmap;
2206
2207 uint regionsizeX = m_regionWidth;
2208 uint regionsizeY = m_regionHeight;
2209
2210 // map is rotated
2211 uint heightmapWidth = regionsizeY + 2;
2212 uint heightmapHeight = regionsizeX + 2;
2213
2214 uint heightmapWidthSamples = heightmapWidth + 1;
2215 uint heightmapHeightSamples = heightmapHeight + 1;
2216
2217 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2218
2219 const float scale = 1.0f;
2220 const float offset = 0.0f;
2221 const float thickness = 10f;
2222 const int wrap = 0;
2223
2224
2225 float hfmin = float.MaxValue;
2226 float hfmax = float.MinValue;
2227 float val;
2228 uint xx;
2229 uint yy;
2230
2231 uint maxXX = regionsizeX - 1;
2232 uint maxYY = regionsizeY - 1;
2233 // flipping map adding one margin all around so things don't fall in edges
2234
2235 uint xt = 0;
2236 xx = 0;
2237
2238 for (uint x = 0; x < heightmapWidthSamples; x++)
2239 {
2240 if (x > 1 && xx < maxXX)
2241 xx++;
2242 yy = 0;
2243 for (uint y = 0; y < heightmapHeightSamples; y++)
2244 {
2245 if (y > 1 && y < maxYY)
2246 yy += regionsizeX;
2247
2248 val = heightMap[yy + xx];
2249 if (val < 0.0f)
2250 val = 0.0f; // no neg terrain as in chode
2251 _heightmap[xt + y] = val;
2252
2253 if (hfmin > val)
2254 hfmin = val;
2255 if (hfmax < val)
2256 hfmax = val;
2257 }
2258 xt += heightmapHeightSamples;
2259 }
2260
2261 lock (OdeLock)
2262 {
2263 IntPtr GroundGeom = IntPtr.Zero;
2264 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
2265 {
2266 RegionTerrain.Remove(pOffset);
2267 if (GroundGeom != IntPtr.Zero)
2268 {
2269 actor_name_map.Remove(GroundGeom);
2270 d.GeomDestroy(GroundGeom);
2271
2272 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
2273 {
2274 TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
2275 TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
2276 TerrainHeightFieldHeights.Remove(GroundGeom);
2277 }
2278 }
2279 }
2280 IntPtr HeightmapData = d.GeomHeightfieldDataCreate();
2281
2282 GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2283
2284 d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0,
2285 heightmapHeight, heightmapWidth ,
2286 (int)heightmapHeightSamples, (int)heightmapWidthSamples, scale,
2287 offset, thickness, wrap);
2288
2289 d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2290
2291 GroundGeom = d.CreateHeightfield(GroundSpace, HeightmapData, 1);
2292
2293 if (GroundGeom != IntPtr.Zero)
2294 {
2295 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
2296 d.GeomSetCollideBits(GroundGeom, 0);
2297
2298 PhysicsActor pa = new NullPhysicsActor();
2299 pa.Name = "Terrain";
2300 pa.PhysicsActorType = (int)ActorTypes.Ground;
2301 actor_name_map[GroundGeom] = pa;
2302
2303// geom_name_map[GroundGeom] = "Terrain";
2304
2305 d.Quaternion q = new d.Quaternion();
2306 q.X = 0.5f;
2307 q.Y = 0.5f;
2308 q.Z = 0.5f;
2309 q.W = 0.5f;
2310
2311 d.GeomSetQuaternion(GroundGeom, ref q);
2312 d.GeomSetPosition(GroundGeom, pOffset.X + m_regionWidth * 0.5f, pOffset.Y + m_regionHeight * 0.5f, 0.0f);
2313 RegionTerrain.Add(pOffset, GroundGeom);
2314 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
2315 TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
2316 }
2317 }
2318 }
2319
2320 public void OSSetTerrain(float[] heightMap, Vector3 pOffset)
2321 {
2322 // assumes 1m size grid and constante size square regions
2323 // needs to know about sims around in future
2324
2325 float[] _heightmap;
2326
2327 uint regionsizeX = m_regionWidth;
2328 uint regionsizeY = m_regionHeight;
2329
2330 uint heightmapWidth = regionsizeX + 2;
2331 uint heightmapHeight = regionsizeY + 2;
2332
2333 uint heightmapWidthSamples = heightmapWidth + 1;
2334 uint heightmapHeightSamples = heightmapHeight + 1;
2335
2336 _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples];
2337
2338
2339 float hfmin = float.MaxValue;
2340// float hfmax = float.MinValue;
2341 float val;
2342
2343
2344 uint maxXX = regionsizeX - 1;
2345 uint maxYY = regionsizeY - 1;
2346 // adding one margin all around so things don't fall in edges
2347
2348 uint xx;
2349 uint yy = 0;
2350 uint yt = 0;
2351
2352 for (uint y = 0; y < heightmapHeightSamples; y++)
2353 {
2354 if (y > 1 && y < maxYY)
2355 yy += regionsizeX;
2356 xx = 0;
2357 for (uint x = 0; x < heightmapWidthSamples; x++)
2358 {
2359 if (x > 1 && x < maxXX)
2360 xx++;
2361
2362 val = heightMap[yy + xx];
2363 if (val < 0.0f)
2364 val = 0.0f; // no neg terrain as in chode
2365 _heightmap[yt + x] = val;
2366
2367 if (hfmin > val)
2368 hfmin = val;
2369// if (hfmax < val)
2370// hfmax = val;
2371 }
2372 yt += heightmapWidthSamples;
2373 }
2374 lock (OdeLock)
2375 {
2376 IntPtr GroundGeom = IntPtr.Zero;
2377 if (RegionTerrain.TryGetValue(pOffset, out GroundGeom))
2378 {
2379 RegionTerrain.Remove(pOffset);
2380 if (GroundGeom != IntPtr.Zero)
2381 {
2382 actor_name_map.Remove(GroundGeom);
2383 d.GeomDestroy(GroundGeom);
2384
2385 if (TerrainHeightFieldHeights.ContainsKey(GroundGeom))
2386 {
2387 if (TerrainHeightFieldHeightsHandlers[GroundGeom].IsAllocated)
2388 TerrainHeightFieldHeightsHandlers[GroundGeom].Free();
2389 TerrainHeightFieldHeightsHandlers.Remove(GroundGeom);
2390 TerrainHeightFieldHeights.Remove(GroundGeom);
2391 }
2392 }
2393 }
2394 IntPtr HeightmapData = d.GeomOSTerrainDataCreate();
2395
2396 const int wrap = 0;
2397 float thickness = hfmin;
2398 if (thickness < 0)
2399 thickness = 1;
2400
2401 GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned);
2402
2403 d.GeomOSTerrainDataBuild(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0, 1.0f,
2404 (int)heightmapWidthSamples, (int)heightmapHeightSamples,
2405 thickness, wrap);
2406
2407// d.GeomOSTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1);
2408 GroundGeom = d.CreateOSTerrain(GroundSpace, HeightmapData, 1);
2409 if (GroundGeom != IntPtr.Zero)
2410 {
2411 d.GeomSetCategoryBits(GroundGeom, (uint)(CollisionCategories.Land));
2412 d.GeomSetCollideBits(GroundGeom, 0);
2413
2414
2415 PhysicsActor pa = new NullPhysicsActor();
2416 pa.Name = "Terrain";
2417 pa.PhysicsActorType = (int)ActorTypes.Ground;
2418 actor_name_map[GroundGeom] = pa;
2419
2420// geom_name_map[GroundGeom] = "Terrain";
2421
2422 d.GeomSetPosition(GroundGeom, pOffset.X + m_regionWidth * 0.5f, pOffset.Y + m_regionHeight * 0.5f, 0.0f);
2423 RegionTerrain.Add(pOffset, GroundGeom);
2424 TerrainHeightFieldHeights.Add(GroundGeom, _heightmap);
2425 TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler);
2426 }
2427 }
2428 }
2429
2430 public override void DeleteTerrain()
2431 {
2432 }
2433
2434 public float GetWaterLevel()
2435 {
2436 return waterlevel;
2437 }
2438
2439 public override bool SupportsCombining()
2440 {
2441 return m_suportCombine;
2442 }
2443
2444 public override void SetWaterLevel(float baseheight)
2445 {
2446 waterlevel = baseheight;
2447 }
2448
2449 public override void Dispose()
2450 {
2451 lock (OdeLock)
2452 {
2453 if (world == IntPtr.Zero)
2454 return;
2455
2456 if (m_meshWorker != null)
2457 m_meshWorker.Stop();
2458
2459 if (m_rayCastManager != null)
2460 {
2461 m_rayCastManager.Dispose();
2462 m_rayCastManager = null;
2463 }
2464
2465 lock (_prims)
2466 {
2467 ChangesQueue.Clear();
2468 foreach (OdePrim prm in _prims)
2469 {
2470 prm.DoAChange(changes.Remove, null);
2471 _collisionEventPrim.Remove(prm);
2472 }
2473 _prims.Clear();
2474 }
2475
2476 OdeCharacter[] chtorem;
2477 lock (_characters)
2478 {
2479 chtorem = new OdeCharacter[_characters.Count];
2480 _characters.CopyTo(chtorem);
2481 }
2482
2483 ChangesQueue.Clear();
2484 foreach (OdeCharacter ch in chtorem)
2485 ch.DoAChange(changes.Remove, null);
2486
2487
2488 foreach (IntPtr GroundGeom in RegionTerrain.Values)
2489 {
2490 if (GroundGeom != IntPtr.Zero)
2491 d.GeomDestroy(GroundGeom);
2492 }
2493
2494 RegionTerrain.Clear();
2495
2496 if (TerrainHeightFieldHeightsHandlers.Count > 0)
2497 {
2498 foreach (GCHandle gch in TerrainHeightFieldHeightsHandlers.Values)
2499 {
2500 if (gch.IsAllocated)
2501 gch.Free();
2502 }
2503 }
2504
2505 TerrainHeightFieldHeightsHandlers.Clear();
2506 TerrainHeightFieldHeights.Clear();
2507
2508 if (ContactgeomsArray != IntPtr.Zero)
2509 {
2510 Marshal.FreeHGlobal(ContactgeomsArray);
2511 ContactgeomsArray = IntPtr.Zero;
2512 }
2513 if (GlobalContactsArray != IntPtr.Zero)
2514 {
2515 Marshal.FreeHGlobal(GlobalContactsArray);
2516 GlobalContactsArray = IntPtr.Zero;
2517 }
2518
2519 d.WorldDestroy(world);
2520 world = IntPtr.Zero;
2521 //d.CloseODE();
2522 }
2523 }
2524
2525 public override Dictionary<uint, float> GetTopColliders()
2526 {
2527 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();
2528 int cnt = 0;
2529 lock (_prims)
2530 {
2531 foreach (OdePrim prm in _prims)
2532 {
2533 if (prm.CollisionScore > 0)
2534 {
2535 returncolliders.Add(prm.LocalID, prm.CollisionScore);
2536 cnt++;
2537 prm.CollisionScore = 0f;
2538 if (cnt > 25)
2539 {
2540 break;
2541 }
2542 }
2543 }
2544 }
2545 return returncolliders;
2546 }
2547
2548 public override bool SupportsRayCast()
2549 {
2550 return true;
2551 }
2552
2553 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod)
2554 {
2555 if (retMethod != null)
2556 {
2557 ODERayRequest req = new ODERayRequest();
2558 req.actor = null;
2559 req.callbackMethod = retMethod;
2560 req.length = length;
2561 req.Normal = direction;
2562 req.Origin = position;
2563 req.Count = 0;
2564 req.filter = RayFilterFlags.AllPrims;
2565
2566 m_rayCastManager.QueueRequest(req);
2567 }
2568 }
2569
2570 public override void RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayCallback retMethod)
2571 {
2572 if (retMethod != null)
2573 {
2574 ODERayRequest req = new ODERayRequest();
2575 req.actor = null;
2576 req.callbackMethod = retMethod;
2577 req.length = length;
2578 req.Normal = direction;
2579 req.Origin = position;
2580 req.Count = Count;
2581 req.filter = RayFilterFlags.AllPrims;
2582
2583 m_rayCastManager.QueueRequest(req);
2584 }
2585 }
2586
2587
2588 public override List<ContactResult> RaycastWorld(Vector3 position, Vector3 direction, float length, int Count)
2589 {
2590 List<ContactResult> ourresults = new List<ContactResult>();
2591 object SyncObject = new object();
2592
2593 RayCallback retMethod = delegate(List<ContactResult> results)
2594 {
2595 lock (SyncObject)
2596 {
2597 ourresults = results;
2598 Monitor.PulseAll(SyncObject);
2599 }
2600 };
2601
2602 ODERayRequest req = new ODERayRequest();
2603 req.actor = null;
2604 req.callbackMethod = retMethod;
2605 req.length = length;
2606 req.Normal = direction;
2607 req.Origin = position;
2608 req.Count = Count;
2609 req.filter = RayFilterFlags.AllPrims;
2610
2611 lock (SyncObject)
2612 {
2613 m_rayCastManager.QueueRequest(req);
2614 if (!Monitor.Wait(SyncObject, 500))
2615 return null;
2616 else
2617 return ourresults;
2618 }
2619 }
2620
2621 public override bool SupportsRaycastWorldFiltered()
2622 {
2623 return true;
2624 }
2625
2626 public override object RaycastWorld(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
2627 {
2628 object SyncObject = new object();
2629 List<ContactResult> ourresults = new List<ContactResult>();
2630
2631 RayCallback retMethod = delegate(List<ContactResult> results)
2632 {
2633 lock (SyncObject)
2634 {
2635 ourresults = results;
2636 Monitor.PulseAll(SyncObject);
2637 }
2638 };
2639
2640 ODERayRequest req = new ODERayRequest();
2641 req.actor = null;
2642 req.callbackMethod = retMethod;
2643 req.length = length;
2644 req.Normal = direction;
2645 req.Origin = position;
2646 req.Count = Count;
2647 req.filter = filter;
2648
2649 lock (SyncObject)
2650 {
2651 m_rayCastManager.QueueRequest(req);
2652 if (!Monitor.Wait(SyncObject, 500))
2653 return null;
2654 else
2655 return ourresults;
2656 }
2657 }
2658
2659 public override List<ContactResult> RaycastActor(PhysicsActor actor, Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags flags)
2660 {
2661 if (actor == null)
2662 return new List<ContactResult>();
2663
2664 IntPtr geom;
2665 if (actor is OdePrim)
2666 geom = ((OdePrim)actor).prim_geom;
2667 else if (actor is OdeCharacter)
2668 geom = ((OdePrim)actor).prim_geom;
2669 else
2670 return new List<ContactResult>();
2671
2672 if (geom == IntPtr.Zero)
2673 return new List<ContactResult>();
2674
2675 List<ContactResult> ourResults = null;
2676 object SyncObject = new object();
2677
2678 RayCallback retMethod = delegate(List<ContactResult> results)
2679 {
2680 lock (SyncObject)
2681 {
2682 ourResults = results;
2683 Monitor.PulseAll(SyncObject);
2684 }
2685 };
2686
2687 ODERayRequest req = new ODERayRequest();
2688 req.actor = actor;
2689 req.callbackMethod = retMethod;
2690 req.length = length;
2691 req.Normal = direction;
2692 req.Origin = position;
2693 req.Count = Count;
2694 req.filter = flags;
2695
2696 lock (SyncObject)
2697 {
2698 m_rayCastManager.QueueRequest(req);
2699 if (!Monitor.Wait(SyncObject, 500))
2700 return new List<ContactResult>();
2701 }
2702
2703 if (ourResults == null)
2704 return new List<ContactResult>();
2705 return ourResults;
2706 }
2707
2708 public override List<ContactResult> BoxProbe(Vector3 position, Vector3 size, Quaternion orientation, int Count, RayFilterFlags flags)
2709 {
2710 List<ContactResult> ourResults = null;
2711 object SyncObject = new object();
2712
2713 ProbeBoxCallback retMethod = delegate(List<ContactResult> results)
2714 {
2715 lock (SyncObject)
2716 {
2717 ourResults = results;
2718 Monitor.PulseAll(SyncObject);
2719 }
2720 };
2721
2722 ODERayRequest req = new ODERayRequest();
2723 req.actor = null;
2724 req.callbackMethod = retMethod;
2725 req.Normal = size;
2726 req.Origin = position;
2727 req.orientation = orientation;
2728 req.Count = Count;
2729 req.filter = flags;
2730
2731 lock (SyncObject)
2732 {
2733 m_rayCastManager.QueueRequest(req);
2734 if (!Monitor.Wait(SyncObject, 500))
2735 return new List<ContactResult>();
2736 }
2737
2738 if (ourResults == null)
2739 return new List<ContactResult>();
2740 return ourResults;
2741 }
2742
2743 public override List<ContactResult> SphereProbe(Vector3 position, float radius, int Count, RayFilterFlags flags)
2744 {
2745 List<ContactResult> ourResults = null;
2746 object SyncObject = new object();
2747
2748 ProbeSphereCallback retMethod = delegate(List<ContactResult> results)
2749 {
2750 ourResults = results;
2751 Monitor.PulseAll(SyncObject);
2752 };
2753
2754 ODERayRequest req = new ODERayRequest();
2755 req.actor = null;
2756 req.callbackMethod = retMethod;
2757 req.length = radius;
2758 req.Origin = position;
2759 req.Count = Count;
2760 req.filter = flags;
2761
2762
2763 lock (SyncObject)
2764 {
2765 m_rayCastManager.QueueRequest(req);
2766 if (!Monitor.Wait(SyncObject, 500))
2767 return new List<ContactResult>();
2768 }
2769
2770 if (ourResults == null)
2771 return new List<ContactResult>();
2772 return ourResults;
2773 }
2774
2775 public override List<ContactResult> PlaneProbe(PhysicsActor actor, Vector4 plane, int Count, RayFilterFlags flags)
2776 {
2777 IntPtr geom = IntPtr.Zero;;
2778
2779 if (actor != null)
2780 {
2781 if (actor is OdePrim)
2782 geom = ((OdePrim)actor).prim_geom;
2783 else if (actor is OdeCharacter)
2784 geom = ((OdePrim)actor).prim_geom;
2785 }
2786
2787 List<ContactResult> ourResults = null;
2788 object SyncObject = new object();
2789
2790 ProbePlaneCallback retMethod = delegate(List<ContactResult> results)
2791 {
2792 ourResults = results;
2793 Monitor.PulseAll(SyncObject);
2794 };
2795
2796 ODERayRequest req = new ODERayRequest();
2797 req.actor = null;
2798 req.callbackMethod = retMethod;
2799 req.length = plane.W;
2800 req.Normal.X = plane.X;
2801 req.Normal.Y = plane.Y;
2802 req.Normal.Z = plane.Z;
2803 req.Count = Count;
2804 req.filter = flags;
2805
2806 lock (SyncObject)
2807 {
2808 m_rayCastManager.QueueRequest(req);
2809 if (!Monitor.Wait(SyncObject, 500))
2810 return new List<ContactResult>();
2811 }
2812
2813 if (ourResults == null)
2814 return new List<ContactResult>();
2815 return ourResults;
2816 }
2817
2818 public override int SitAvatar(PhysicsActor actor, Vector3 AbsolutePosition, Vector3 CameraPosition, Vector3 offset, Vector3 AvatarSize, SitAvatarCallback PhysicsSitResponse)
2819 {
2820 Util.FireAndForget( delegate
2821 {
2822 ODESitAvatar sitAvatar = new ODESitAvatar(this, m_rayCastManager);
2823 if(sitAvatar != null)
2824 sitAvatar.Sit(actor, AbsolutePosition, CameraPosition, offset, AvatarSize, PhysicsSitResponse);
2825 });
2826 return 1;
2827 }
2828
2829 }
2830}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs b/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs
new file mode 100644
index 0000000..214205d
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/ODESitAvatar.cs
@@ -0,0 +1,356 @@
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// Ubit Umarov 2012
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Runtime.InteropServices;
32using System.Text;
33using OpenSim.Framework;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OdeAPI;
36using log4net;
37using OpenMetaverse;
38
39namespace OpenSim.Region.PhysicsModule.ubOde
40{
41 /// <summary>
42 /// </summary>
43 public class ODESitAvatar
44 {
45 private ODEScene m_scene;
46 private ODERayCastRequestManager m_raymanager;
47
48 public ODESitAvatar(ODEScene pScene, ODERayCastRequestManager raymanager)
49 {
50 m_scene = pScene;
51 m_raymanager = raymanager;
52 }
53
54 private static Vector3 SitAjust = new Vector3(0, 0, 0.4f);
55 private const RayFilterFlags RaySitFlags = RayFilterFlags.AllPrims | RayFilterFlags.ClosestHit;
56
57 private void RotAroundZ(float x, float y, ref Quaternion ori)
58 {
59 double ang = Math.Atan2(y, x);
60 ang *= 0.5d;
61 float s = (float)Math.Sin(ang);
62 float c = (float)Math.Cos(ang);
63
64 ori.X = 0;
65 ori.Y = 0;
66 ori.Z = s;
67 ori.W = c;
68 }
69
70
71 public void Sit(PhysicsActor actor, Vector3 avPos, Vector3 avCameraPosition, Vector3 offset, Vector3 avOffset, SitAvatarCallback PhysicsSitResponse)
72 {
73 if (!m_scene.haveActor(actor) || !(actor is OdePrim) || ((OdePrim)actor).prim_geom == IntPtr.Zero)
74 {
75 PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
76 return;
77 }
78
79 IntPtr geom = ((OdePrim)actor).prim_geom;
80
81 Vector3 geopos = d.GeomGetPositionOMV(geom);
82 Quaternion geomOri = d.GeomGetQuaternionOMV(geom);
83
84// Vector3 geopos = actor.Position;
85// Quaternion geomOri = actor.Orientation;
86
87 Quaternion geomInvOri = Quaternion.Conjugate(geomOri);
88
89 Quaternion ori = Quaternion.Identity;
90
91 Vector3 rayDir = geopos + offset - avCameraPosition;
92
93 float raylen = rayDir.Length();
94 if (raylen < 0.001f)
95 {
96 PhysicsSitResponse(-1, actor.LocalID, offset, Quaternion.Identity);
97 return;
98 }
99 float t = 1 / raylen;
100 rayDir.X *= t;
101 rayDir.Y *= t;
102 rayDir.Z *= t;
103
104 raylen += 30f; // focal point may be far
105 List<ContactResult> rayResults;
106
107 rayResults = m_scene.RaycastActor(actor, avCameraPosition, rayDir, raylen, 1, RaySitFlags);
108 if (rayResults.Count == 0)
109 {
110/* if this fundamental ray failed, then just fail so user can try another spot and not be sitted far on a big prim
111 d.AABB aabb;
112 d.GeomGetAABB(geom, out aabb);
113 offset = new Vector3(avOffset.X, 0, aabb.MaxZ + avOffset.Z - geopos.Z);
114 ori = geomInvOri;
115 offset *= geomInvOri;
116 PhysicsSitResponse(1, actor.LocalID, offset, ori);
117*/
118 PhysicsSitResponse(0, actor.LocalID, offset, ori);
119 return;
120 }
121
122 int status = 1;
123
124 offset = rayResults[0].Pos - geopos;
125
126 d.GeomClassID geoclass = d.GeomGetClass(geom);
127
128 if (geoclass == d.GeomClassID.SphereClass)
129 {
130 float r = d.GeomSphereGetRadius(geom);
131
132 offset.Normalize();
133 offset *= r;
134
135 RotAroundZ(offset.X, offset.Y, ref ori);
136
137 if (r < 0.4f)
138 {
139 offset = new Vector3(0, 0, r);
140 }
141 else
142 {
143 if (offset.Z < 0.4f)
144 {
145 t = offset.Z;
146 float rsq = r * r;
147
148 t = 1.0f / (rsq - t * t);
149 offset.X *= t;
150 offset.Y *= t;
151 offset.Z = 0.4f;
152 t = rsq - 0.16f;
153 offset.X *= t;
154 offset.Y *= t;
155 }
156 else if (r > 0.8f && offset.Z > 0.8f * r)
157 {
158 status = 3;
159 avOffset.X = -avOffset.X;
160 avOffset.Z *= 1.6f;
161 }
162 }
163
164 offset += avOffset * ori;
165
166 ori = geomInvOri * ori;
167 offset *= geomInvOri;
168
169 PhysicsSitResponse(status, actor.LocalID, offset, ori);
170 return;
171 }
172
173 Vector3 norm = rayResults[0].Normal;
174
175 if (norm.Z < -0.4f)
176 {
177 PhysicsSitResponse(0, actor.LocalID, offset, Quaternion.Identity);
178 return;
179 }
180
181
182 float SitNormX = -rayDir.X;
183 float SitNormY = -rayDir.Y;
184
185 Vector3 pivot = geopos + offset;
186
187 float edgeNormalX = norm.X;
188 float edgeNormalY = norm.Y;
189 float edgeDirX = -rayDir.X;
190 float edgeDirY = -rayDir.Y;
191 Vector3 edgePos = rayResults[0].Pos;
192 float edgeDist = float.MaxValue;
193
194 bool foundEdge = false;
195
196 if (norm.Z < 0.5f)
197 {
198 float rayDist = 4.0f;
199
200 for (int i = 0; i < 6; i++)
201 {
202 pivot.X -= 0.01f * norm.X;
203 pivot.Y -= 0.01f * norm.Y;
204 pivot.Z -= 0.01f * norm.Z;
205
206 rayDir.X = -norm.X * norm.Z;
207 rayDir.Y = -norm.Y * norm.Z;
208 rayDir.Z = 1.0f - norm.Z * norm.Z;
209 rayDir.Normalize();
210
211 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
212 if (rayResults.Count == 0)
213 break;
214
215 if (Math.Abs(rayResults[0].Normal.Z) < 0.7f)
216 {
217 rayDist -= rayResults[0].Depth;
218 if (rayDist < 0f)
219 break;
220
221 pivot = rayResults[0].Pos;
222 norm = rayResults[0].Normal;
223 edgeNormalX = norm.X;
224 edgeNormalY = norm.Y;
225 edgeDirX = -rayDir.X;
226 edgeDirY = -rayDir.Y;
227 }
228 else
229 {
230 foundEdge = true;
231 edgePos = rayResults[0].Pos;
232 break;
233 }
234 }
235
236 if (!foundEdge)
237 {
238 PhysicsSitResponse(0, actor.LocalID, offset, ori);
239 return;
240 }
241 avOffset.X *= 0.5f;
242 }
243
244 else if (norm.Z > 0.866f)
245 {
246 float toCamBaseX = avCameraPosition.X - pivot.X;
247 float toCamBaseY = avCameraPosition.Y - pivot.Y;
248 float toCamX = toCamBaseX;
249 float toCamY = toCamBaseY;
250
251 for (int j = 0; j < 4; j++)
252 {
253 float rayDist = 1.0f;
254 float curEdgeDist = 0.0f;
255
256 for (int i = 0; i < 3; i++)
257 {
258 pivot.Z -= 0.01f;
259 rayDir.X = toCamX;
260 rayDir.Y = toCamY;
261 rayDir.Z = (-toCamX * norm.X - toCamY * norm.Y) / norm.Z;
262 rayDir.Normalize();
263
264 rayResults = m_scene.RaycastActor(actor, pivot, rayDir, rayDist, 1, RayFilterFlags.AllPrims);
265 if (rayResults.Count == 0)
266 break;
267
268 curEdgeDist += rayResults[0].Depth;
269
270 if (rayResults[0].Normal.Z > 0.5f)
271 {
272 rayDist -= rayResults[0].Depth;
273 if (rayDist < 0f)
274 break;
275
276 pivot = rayResults[0].Pos;
277 norm = rayResults[0].Normal;
278 }
279 else
280 {
281 foundEdge = true;
282 if (curEdgeDist < edgeDist)
283 {
284 edgeDist = curEdgeDist;
285 edgeNormalX = rayResults[0].Normal.X;
286 edgeNormalY = rayResults[0].Normal.Y;
287 edgeDirX = rayDir.X;
288 edgeDirY = rayDir.Y;
289 edgePos = rayResults[0].Pos;
290 }
291 break;
292 }
293 }
294 if (foundEdge && edgeDist < 0.2f)
295 break;
296
297 pivot = geopos + offset;
298
299 switch (j)
300 {
301 case 0:
302 toCamX = -toCamBaseY;
303 toCamY = toCamBaseX;
304 break;
305 case 1:
306 toCamX = toCamBaseY;
307 toCamY = -toCamBaseX;
308 break;
309 case 2:
310 toCamX = -toCamBaseX;
311 toCamY = -toCamBaseY;
312 break;
313 default:
314 break;
315 }
316 }
317
318 if (!foundEdge)
319 {
320 avOffset.X = -avOffset.X;
321 avOffset.Z *= 1.6f;
322
323 RotAroundZ(SitNormX, SitNormY, ref ori);
324
325 offset += avOffset * ori;
326
327 ori = geomInvOri * ori;
328 offset *= geomInvOri;
329
330 PhysicsSitResponse(3, actor.LocalID, offset, ori);
331 return;
332 }
333 avOffset.X *= 0.5f;
334 }
335
336 SitNormX = edgeNormalX;
337 SitNormY = edgeNormalY;
338 if (edgeDirX * SitNormX + edgeDirY * SitNormY < 0)
339 {
340 SitNormX = -SitNormX;
341 SitNormY = -SitNormY;
342 }
343
344 RotAroundZ(SitNormX, SitNormY, ref ori);
345
346 offset = edgePos + avOffset * ori;
347 offset -= geopos;
348
349 ori = geomInvOri * ori;
350 offset *= geomInvOri;
351
352 PhysicsSitResponse(1, actor.LocalID, offset, ori);
353 return;
354 }
355 }
356}
diff --git a/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..293454a
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOde/Properties/AssemblyInfo.cs
@@ -0,0 +1,61 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Reflection;
29using System.Runtime.InteropServices;
30using Mono.Addins;
31
32// Information about this assembly is defined by the following
33// attributes.
34//
35// change them to the information which is associated with the assembly
36// you compile.
37
38[assembly : AssemblyTitle("OpenSim.Region.PhysicsModule.ubOde")]
39[assembly : AssemblyDescription("Ubit Variation of ODE")]
40[assembly : AssemblyConfiguration("")]
41[assembly : AssemblyCompany("http://opensimulator.org")]
42[assembly : AssemblyProduct("ubOde")]
43[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
44[assembly : AssemblyTrademark("")]
45[assembly : AssemblyCulture("")]
46
47// This sets the default COM visibility of types in the assembly to invisible.
48// If you need to expose a type to COM, use [ComVisible(true)] on that type.
49
50[assembly : ComVisible(false)]
51
52// The assembly version has following format :
53//
54// Major.Minor.Build.Revision
55//
56// You can specify all values by your own or you can build default build and revision
57// numbers with the '*' character (the default):
58
59[assembly : AssemblyVersion("0.8.2.*")]
60[assembly: Addin("OpenSim.Region.PhysicsModule.ubOde", OpenSim.VersionInfo.VersionNumber)]
61[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] \ No newline at end of file
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/HelperTypes.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/HelperTypes.cs
new file mode 100644
index 0000000..ea37301
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/HelperTypes.cs
@@ -0,0 +1,340 @@
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.Globalization;
32using OpenMetaverse;
33using OpenSim.Region.PhysicsModules.SharedBase;
34using OpenSim.Region.PhysicsModule.ubODEMeshing;
35
36public class Vertex : IComparable<Vertex>
37{
38 Vector3 vector;
39
40 public float X
41 {
42 get { return vector.X; }
43 set { vector.X = value; }
44 }
45
46 public float Y
47 {
48 get { return vector.Y; }
49 set { vector.Y = value; }
50 }
51
52 public float Z
53 {
54 get { return vector.Z; }
55 set { vector.Z = value; }
56 }
57
58 public Vertex(float x, float y, float z)
59 {
60 vector.X = x;
61 vector.Y = y;
62 vector.Z = z;
63 }
64
65 public Vertex normalize()
66 {
67 float tlength = vector.Length();
68 if (tlength != 0f)
69 {
70 float mul = 1.0f / tlength;
71 return new Vertex(vector.X * mul, vector.Y * mul, vector.Z * mul);
72 }
73 else
74 {
75 return new Vertex(0f, 0f, 0f);
76 }
77 }
78
79 public Vertex cross(Vertex v)
80 {
81 return new Vertex(vector.Y * v.Z - vector.Z * v.Y, vector.Z * v.X - vector.X * v.Z, vector.X * v.Y - vector.Y * v.X);
82 }
83
84 // disable warning: mono compiler moans about overloading
85 // operators hiding base operator but should not according to C#
86 // language spec
87#pragma warning disable 0108
88 public static Vertex operator *(Vertex v, Quaternion q)
89 {
90 // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/
91
92 Vertex v2 = new Vertex(0f, 0f, 0f);
93
94 v2.X = q.W * q.W * v.X +
95 2f * q.Y * q.W * v.Z -
96 2f * q.Z * q.W * v.Y +
97 q.X * q.X * v.X +
98 2f * q.Y * q.X * v.Y +
99 2f * q.Z * q.X * v.Z -
100 q.Z * q.Z * v.X -
101 q.Y * q.Y * v.X;
102
103 v2.Y =
104 2f * q.X * q.Y * v.X +
105 q.Y * q.Y * v.Y +
106 2f * q.Z * q.Y * v.Z +
107 2f * q.W * q.Z * v.X -
108 q.Z * q.Z * v.Y +
109 q.W * q.W * v.Y -
110 2f * q.X * q.W * v.Z -
111 q.X * q.X * v.Y;
112
113 v2.Z =
114 2f * q.X * q.Z * v.X +
115 2f * q.Y * q.Z * v.Y +
116 q.Z * q.Z * v.Z -
117 2f * q.W * q.Y * v.X -
118 q.Y * q.Y * v.Z +
119 2f * q.W * q.X * v.Y -
120 q.X * q.X * v.Z +
121 q.W * q.W * v.Z;
122
123 return v2;
124 }
125
126 public static Vertex operator +(Vertex v1, Vertex v2)
127 {
128 return new Vertex(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
129 }
130
131 public static Vertex operator -(Vertex v1, Vertex v2)
132 {
133 return new Vertex(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
134 }
135
136 public static Vertex operator *(Vertex v1, Vertex v2)
137 {
138 return new Vertex(v1.X * v2.X, v1.Y * v2.Y, v1.Z * v2.Z);
139 }
140
141 public static Vertex operator +(Vertex v1, float am)
142 {
143 v1.X += am;
144 v1.Y += am;
145 v1.Z += am;
146 return v1;
147 }
148
149 public static Vertex operator -(Vertex v1, float am)
150 {
151 v1.X -= am;
152 v1.Y -= am;
153 v1.Z -= am;
154 return v1;
155 }
156
157 public static Vertex operator *(Vertex v1, float am)
158 {
159 v1.X *= am;
160 v1.Y *= am;
161 v1.Z *= am;
162 return v1;
163 }
164
165 public static Vertex operator /(Vertex v1, float am)
166 {
167 if (am == 0f)
168 {
169 return new Vertex(0f,0f,0f);
170 }
171 float mul = 1.0f / am;
172 v1.X *= mul;
173 v1.Y *= mul;
174 v1.Z *= mul;
175 return v1;
176 }
177#pragma warning restore 0108
178
179
180 public float dot(Vertex v)
181 {
182 return X * v.X + Y * v.Y + Z * v.Z;
183 }
184
185 public Vertex(Vector3 v)
186 {
187 vector = v;
188 }
189
190 public Vertex Clone()
191 {
192 return new Vertex(X, Y, Z);
193 }
194
195 public static Vertex FromAngle(double angle)
196 {
197 return new Vertex((float) Math.Cos(angle), (float) Math.Sin(angle), 0.0f);
198 }
199
200 public float Length()
201 {
202 return vector.Length();
203 }
204
205 public virtual bool Equals(Vertex v, float tolerance)
206 {
207 Vertex diff = this - v;
208 float d = diff.Length();
209 if (d < tolerance)
210 return true;
211
212 return false;
213 }
214
215
216 public int CompareTo(Vertex other)
217 {
218 if (X < other.X)
219 return -1;
220
221 if (X > other.X)
222 return 1;
223
224 if (Y < other.Y)
225 return -1;
226
227 if (Y > other.Y)
228 return 1;
229
230 if (Z < other.Z)
231 return -1;
232
233 if (Z > other.Z)
234 return 1;
235
236 return 0;
237 }
238
239 public static bool operator >(Vertex me, Vertex other)
240 {
241 return me.CompareTo(other) > 0;
242 }
243
244 public static bool operator <(Vertex me, Vertex other)
245 {
246 return me.CompareTo(other) < 0;
247 }
248
249 public String ToRaw()
250 {
251 // Why this stuff with the number formatter?
252 // Well, the raw format uses the english/US notation of numbers
253 // where the "," separates groups of 1000 while the "." marks the border between 1 and 10E-1.
254 // The german notation uses these characters exactly vice versa!
255 // The Float.ToString() routine is a localized one, giving different results depending on the country
256 // settings your machine works with. Unusable for a machine readable file format :-(
257 NumberFormatInfo nfi = new NumberFormatInfo();
258 nfi.NumberDecimalSeparator = ".";
259 nfi.NumberDecimalDigits = 6;
260
261 String s1 = X.ToString(nfi) + " " + Y.ToString(nfi) + " " + Z.ToString(nfi);
262
263 return s1;
264 }
265}
266
267public class Triangle
268{
269 public Vertex v1;
270 public Vertex v2;
271 public Vertex v3;
272
273 public Triangle(Vertex _v1, Vertex _v2, Vertex _v3)
274 {
275 v1 = _v1;
276 v2 = _v2;
277 v3 = _v3;
278 }
279
280 public Triangle(float _v1x,float _v1y,float _v1z,
281 float _v2x,float _v2y,float _v2z,
282 float _v3x,float _v3y,float _v3z)
283 {
284 v1 = new Vertex(_v1x, _v1y, _v1z);
285 v2 = new Vertex(_v2x, _v2y, _v2z);
286 v3 = new Vertex(_v3x, _v3y, _v3z);
287 }
288
289 public override String ToString()
290 {
291 NumberFormatInfo nfi = new NumberFormatInfo();
292 nfi.CurrencyDecimalDigits = 2;
293 nfi.CurrencyDecimalSeparator = ".";
294
295 String s1 = "<" + v1.X.ToString(nfi) + "," + v1.Y.ToString(nfi) + "," + v1.Z.ToString(nfi) + ">";
296 String s2 = "<" + v2.X.ToString(nfi) + "," + v2.Y.ToString(nfi) + "," + v2.Z.ToString(nfi) + ">";
297 String s3 = "<" + v3.X.ToString(nfi) + "," + v3.Y.ToString(nfi) + "," + v3.Z.ToString(nfi) + ">";
298
299 return s1 + ";" + s2 + ";" + s3;
300 }
301
302 public Vector3 getNormal()
303 {
304 // Vertices
305
306 // Vectors for edges
307 Vector3 e1;
308 Vector3 e2;
309
310 e1 = new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
311 e2 = new Vector3(v1.X - v3.X, v1.Y - v3.Y, v1.Z - v3.Z);
312
313 // Cross product for normal
314 Vector3 n = Vector3.Cross(e1, e2);
315
316 // Length
317 float l = n.Length();
318
319 // Normalized "normal"
320 n = n/l;
321
322 return n;
323 }
324
325 public void invertNormal()
326 {
327 Vertex vt;
328 vt = v1;
329 v1 = v2;
330 v2 = vt;
331 }
332
333 // Dumps a triangle in the "raw faces" format, blender can import. This is for visualisation and
334 // debugging purposes
335 public String ToStringRaw()
336 {
337 String output = v1.ToRaw() + " " + v2.ToRaw() + " " + v3.ToRaw();
338 return output;
339 }
340}
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs
new file mode 100644
index 0000000..97501a4
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Mesh.cs
@@ -0,0 +1,633 @@
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.Runtime.InteropServices;
32using OpenSim.Region.PhysicsModules.SharedBase;
33using PrimMesher;
34using OpenMetaverse;
35using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary;
37
38namespace OpenSim.Region.PhysicsModule.ubODEMeshing
39{
40 public class MeshBuildingData
41 {
42 public Dictionary<Vertex, int> m_vertices;
43 public List<Triangle> m_triangles;
44 public float m_obbXmin;
45 public float m_obbXmax;
46 public float m_obbYmin;
47 public float m_obbYmax;
48 public float m_obbZmin;
49 public float m_obbZmax;
50 public Vector3 m_centroid;
51 public int m_centroidDiv;
52 }
53
54 [Serializable()]
55 public class Mesh : IMesh
56 {
57 float[] vertices;
58 int[] indexes;
59 Vector3 m_obb;
60 Vector3 m_obboffset;
61 [NonSerialized()]
62 MeshBuildingData m_bdata;
63 [NonSerialized()]
64 GCHandle vhandler;
65 [NonSerialized()]
66 GCHandle ihandler;
67 [NonSerialized()]
68 IntPtr m_verticesPtr = IntPtr.Zero;
69 [NonSerialized()]
70 IntPtr m_indicesPtr = IntPtr.Zero;
71 [NonSerialized()]
72 int m_vertexCount = 0;
73 [NonSerialized()]
74 int m_indexCount = 0;
75
76 public int RefCount { get; set; }
77 public AMeshKey Key { get; set; }
78
79 private class vertexcomp : IEqualityComparer<Vertex>
80 {
81 public bool Equals(Vertex v1, Vertex v2)
82 {
83 if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z)
84 return true;
85 else
86 return false;
87 }
88 public int GetHashCode(Vertex v)
89 {
90 int a = v.X.GetHashCode();
91 int b = v.Y.GetHashCode();
92 int c = v.Z.GetHashCode();
93 return (a << 16) ^ (b << 8) ^ c;
94 }
95 }
96
97 public Mesh()
98 {
99 vertexcomp vcomp = new vertexcomp();
100
101 m_bdata = new MeshBuildingData();
102 m_bdata.m_vertices = new Dictionary<Vertex, int>(vcomp);
103 m_bdata.m_triangles = new List<Triangle>();
104 m_bdata.m_centroid = Vector3.Zero;
105 m_bdata.m_centroidDiv = 0;
106 m_bdata.m_obbXmin = float.MaxValue;
107 m_bdata.m_obbXmax = float.MinValue;
108 m_bdata.m_obbYmin = float.MaxValue;
109 m_bdata.m_obbYmax = float.MinValue;
110 m_bdata.m_obbZmin = float.MaxValue;
111 m_bdata.m_obbZmax = float.MinValue;
112 m_obb = new Vector3(0.5f, 0.5f, 0.5f);
113 m_obboffset = Vector3.Zero;
114 }
115
116
117 public Mesh Scale(Vector3 scale)
118 {
119 if (m_verticesPtr == null || m_indicesPtr == null)
120 return null;
121
122 Mesh result = new Mesh();
123
124 float x = scale.X;
125 float y = scale.Y;
126 float z = scale.Z;
127
128 float tmp;
129 tmp = m_obb.X * x;
130 if(tmp < 0.0005f)
131 tmp = 0.0005f;
132 result.m_obb.X = tmp;
133
134 tmp = m_obb.Y * y;
135 if(tmp < 0.0005f)
136 tmp = 0.0005f;
137 result.m_obb.Y = tmp;
138
139 tmp = m_obb.Z * z;
140 if(tmp < 0.0005f)
141 tmp = 0.0005f;
142 result.m_obb.Z = tmp;
143
144 result.m_obboffset.X = m_obboffset.X * x;
145 result.m_obboffset.Y = m_obboffset.Y * y;
146 result.m_obboffset.Z = m_obboffset.Z * z;
147
148 result.vertices = new float[vertices.Length];
149 int j = 0;
150 for (int i = 0; i < m_vertexCount; i++)
151 {
152 result.vertices[j] = vertices[j] * x;
153 j++;
154 result.vertices[j] = vertices[j] * y;
155 j++;
156 result.vertices[j] = vertices[j] * z;
157 j++;
158 }
159
160 result.indexes = new int[indexes.Length];
161 indexes.CopyTo(result.indexes,0);
162
163 result.pinMemory();
164
165 return result;
166 }
167
168 public Mesh Clone()
169 {
170 Mesh result = new Mesh();
171
172 if (m_bdata != null)
173 {
174 result.m_bdata = new MeshBuildingData();
175 foreach (Triangle t in m_bdata.m_triangles)
176 {
177 result.Add(new Triangle(t.v1.Clone(), t.v2.Clone(), t.v3.Clone()));
178 }
179 result.m_bdata.m_centroid = m_bdata.m_centroid;
180 result.m_bdata.m_centroidDiv = m_bdata.m_centroidDiv;
181 result.m_bdata.m_obbXmin = m_bdata.m_obbXmin;
182 result.m_bdata.m_obbXmax = m_bdata.m_obbXmax;
183 result.m_bdata.m_obbYmin = m_bdata.m_obbYmin;
184 result.m_bdata.m_obbYmax = m_bdata.m_obbYmax;
185 result.m_bdata.m_obbZmin = m_bdata.m_obbZmin;
186 result.m_bdata.m_obbZmax = m_bdata.m_obbZmax;
187 }
188 result.m_obb = m_obb;
189 result.m_obboffset = m_obboffset;
190 return result;
191 }
192
193 public void addVertexLStats(Vertex v)
194 {
195 float x = v.X;
196 float y = v.Y;
197 float z = v.Z;
198
199 m_bdata.m_centroid.X += x;
200 m_bdata.m_centroid.Y += y;
201 m_bdata.m_centroid.Z += z;
202 m_bdata.m_centroidDiv++;
203
204 if (x > m_bdata.m_obbXmax)
205 m_bdata.m_obbXmax = x;
206 if (x < m_bdata.m_obbXmin)
207 m_bdata.m_obbXmin = x;
208
209 if (y > m_bdata.m_obbYmax)
210 m_bdata.m_obbYmax = y;
211 if (y < m_bdata.m_obbYmin)
212 m_bdata.m_obbYmin = y;
213
214 if (z > m_bdata.m_obbZmax)
215 m_bdata.m_obbZmax = z;
216 if (z < m_bdata.m_obbZmin)
217 m_bdata.m_obbZmin = z;
218
219 }
220
221 public void Add(Triangle triangle)
222 {
223 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
224 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
225
226
227 triangle.v1.X = (float)Math.Round(triangle.v1.X, 6);
228 triangle.v1.Y = (float)Math.Round(triangle.v1.Y, 6);
229 triangle.v1.Z = (float)Math.Round(triangle.v1.Z, 6);
230 triangle.v2.X = (float)Math.Round(triangle.v2.X, 6);
231 triangle.v2.Y = (float)Math.Round(triangle.v2.Y, 6);
232 triangle.v2.Z = (float)Math.Round(triangle.v2.Z, 6);
233 triangle.v3.X = (float)Math.Round(triangle.v3.X, 6);
234 triangle.v3.Y = (float)Math.Round(triangle.v3.Y, 6);
235 triangle.v3.Z = (float)Math.Round(triangle.v3.Z, 6);
236
237 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
238 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
239 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
240 )
241 {
242 return;
243 }
244
245 if (m_bdata.m_vertices.Count == 0)
246 {
247 m_bdata.m_centroidDiv = 0;
248 m_bdata.m_centroid = Vector3.Zero;
249 }
250
251 if (!m_bdata.m_vertices.ContainsKey(triangle.v1))
252 {
253 m_bdata.m_vertices[triangle.v1] = m_bdata.m_vertices.Count;
254 addVertexLStats(triangle.v1);
255 }
256 if (!m_bdata.m_vertices.ContainsKey(triangle.v2))
257 {
258 m_bdata.m_vertices[triangle.v2] = m_bdata.m_vertices.Count;
259 addVertexLStats(triangle.v2);
260 }
261 if (!m_bdata.m_vertices.ContainsKey(triangle.v3))
262 {
263 m_bdata.m_vertices[triangle.v3] = m_bdata.m_vertices.Count;
264 addVertexLStats(triangle.v3);
265 }
266 m_bdata.m_triangles.Add(triangle);
267 }
268
269 public Vector3 GetCentroid()
270 {
271 return m_obboffset;
272
273 }
274
275 public Vector3 GetOBB()
276 {
277 return m_obb;
278/*
279 float x, y, z;
280 if (m_bdata.m_centroidDiv > 0)
281 {
282 x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
283 y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
284 z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
285 }
286 else // ??
287 {
288 x = 0.5f;
289 y = 0.5f;
290 z = 0.5f;
291 }
292 return new Vector3(x, y, z);
293*/
294 }
295
296 public int numberVertices()
297 {
298 return m_bdata.m_vertices.Count;
299 }
300
301 public int numberTriangles()
302 {
303 return m_bdata.m_triangles.Count;
304 }
305
306 public List<Vector3> getVertexList()
307 {
308 List<Vector3> result = new List<Vector3>();
309 foreach (Vertex v in m_bdata.m_vertices.Keys)
310 {
311 result.Add(new Vector3(v.X, v.Y, v.Z));
312 }
313 return result;
314 }
315
316 public float[] getVertexListAsFloat()
317 {
318 if (m_bdata.m_vertices == null)
319 throw new NotSupportedException();
320 float[] result = new float[m_bdata.m_vertices.Count * 3];
321 foreach (KeyValuePair<Vertex, int> kvp in m_bdata.m_vertices)
322 {
323 Vertex v = kvp.Key;
324 int i = kvp.Value;
325 result[3 * i + 0] = v.X;
326 result[3 * i + 1] = v.Y;
327 result[3 * i + 2] = v.Z;
328 }
329 return result;
330 }
331
332 public float[] getVertexListAsFloatLocked()
333 {
334 return null;
335 }
336
337 public void getVertexListAsPtrToFloatArray(out IntPtr _vertices, out int vertexStride, out int vertexCount)
338 {
339 // A vertex is 3 floats
340 vertexStride = 3 * sizeof(float);
341
342 // If there isn't an unmanaged array allocated yet, do it now
343 if (m_verticesPtr == IntPtr.Zero && m_bdata != null)
344 {
345 vertices = getVertexListAsFloat();
346 // Each vertex is 3 elements (floats)
347 m_vertexCount = vertices.Length / 3;
348 vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
349 m_verticesPtr = vhandler.AddrOfPinnedObject();
350 GC.AddMemoryPressure(Buffer.ByteLength(vertices));
351 }
352 _vertices = m_verticesPtr;
353 vertexCount = m_vertexCount;
354 }
355
356 public int[] getIndexListAsInt()
357 {
358 if (m_bdata.m_triangles == null)
359 throw new NotSupportedException();
360 int[] result = new int[m_bdata.m_triangles.Count * 3];
361 for (int i = 0; i < m_bdata.m_triangles.Count; i++)
362 {
363 Triangle t = m_bdata.m_triangles[i];
364 result[3 * i + 0] = m_bdata.m_vertices[t.v1];
365 result[3 * i + 1] = m_bdata.m_vertices[t.v2];
366 result[3 * i + 2] = m_bdata.m_vertices[t.v3];
367 }
368 return result;
369 }
370
371 /// <summary>
372 /// creates a list of index values that defines triangle faces. THIS METHOD FREES ALL NON-PINNED MESH DATA
373 /// </summary>
374 /// <returns></returns>
375 public int[] getIndexListAsIntLocked()
376 {
377 return null;
378 }
379
380 public void getIndexListAsPtrToIntArray(out IntPtr indices, out int triStride, out int indexCount)
381 {
382 // If there isn't an unmanaged array allocated yet, do it now
383 if (m_indicesPtr == IntPtr.Zero && m_bdata != null)
384 {
385 indexes = getIndexListAsInt();
386 m_indexCount = indexes.Length;
387 ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
388 m_indicesPtr = ihandler.AddrOfPinnedObject();
389 GC.AddMemoryPressure(Buffer.ByteLength(indexes));
390 }
391 // A triangle is 3 ints (indices)
392 triStride = 3 * sizeof(int);
393 indices = m_indicesPtr;
394 indexCount = m_indexCount;
395 }
396
397 public void releasePinned()
398 {
399 if (m_verticesPtr != IntPtr.Zero)
400 {
401 vhandler.Free();
402 vertices = null;
403 m_verticesPtr = IntPtr.Zero;
404 }
405 if (m_indicesPtr != IntPtr.Zero)
406 {
407 ihandler.Free();
408 indexes = null;
409 m_indicesPtr = IntPtr.Zero;
410 }
411 }
412
413 /// <summary>
414 /// frees up the source mesh data to minimize memory - call this method after calling get*Locked() functions
415 /// </summary>
416 public void releaseSourceMeshData()
417 {
418 if (m_bdata != null)
419 {
420 m_bdata.m_triangles = null;
421 m_bdata.m_vertices = null;
422 }
423 }
424
425 public void releaseBuildingMeshData()
426 {
427 if (m_bdata != null)
428 {
429 m_bdata.m_triangles = null;
430 m_bdata.m_vertices = null;
431 m_bdata = null;
432 }
433 }
434
435 public void Append(IMesh newMesh)
436 {
437 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
438 throw new NotSupportedException("Attempt to Append to a pinned Mesh");
439
440 if (!(newMesh is Mesh))
441 return;
442
443 foreach (Triangle t in ((Mesh)newMesh).m_bdata.m_triangles)
444 Add(t);
445 }
446
447 // Do a linear transformation of mesh.
448 public void TransformLinear(float[,] matrix, float[] offset)
449 {
450 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
451 throw new NotSupportedException("Attempt to TransformLinear a pinned Mesh");
452
453 foreach (Vertex v in m_bdata.m_vertices.Keys)
454 {
455 if (v == null)
456 continue;
457 float x, y, z;
458 x = v.X*matrix[0, 0] + v.Y*matrix[1, 0] + v.Z*matrix[2, 0];
459 y = v.X*matrix[0, 1] + v.Y*matrix[1, 1] + v.Z*matrix[2, 1];
460 z = v.X*matrix[0, 2] + v.Y*matrix[1, 2] + v.Z*matrix[2, 2];
461 v.X = x + offset[0];
462 v.Y = y + offset[1];
463 v.Z = z + offset[2];
464 }
465 }
466
467 public void DumpRaw(String path, String name, String title)
468 {
469 if (path == null)
470 return;
471 if (m_bdata == null)
472 return;
473 String fileName = name + "_" + title + ".raw";
474 String completePath = System.IO.Path.Combine(path, fileName);
475 StreamWriter sw = new StreamWriter(completePath);
476 foreach (Triangle t in m_bdata.m_triangles)
477 {
478 String s = t.ToStringRaw();
479 sw.WriteLine(s);
480 }
481 sw.Close();
482 }
483
484 public void TrimExcess()
485 {
486 m_bdata.m_triangles.TrimExcess();
487 }
488
489 public void pinMemory()
490 {
491 m_vertexCount = vertices.Length / 3;
492 vhandler = GCHandle.Alloc(vertices, GCHandleType.Pinned);
493 m_verticesPtr = vhandler.AddrOfPinnedObject();
494 GC.AddMemoryPressure(Buffer.ByteLength(vertices));
495
496 m_indexCount = indexes.Length;
497 ihandler = GCHandle.Alloc(indexes, GCHandleType.Pinned);
498 m_indicesPtr = ihandler.AddrOfPinnedObject();
499 GC.AddMemoryPressure(Buffer.ByteLength(indexes));
500 }
501
502 public void PrepForOde()
503 {
504 // If there isn't an unmanaged array allocated yet, do it now
505 if (m_verticesPtr == IntPtr.Zero)
506 vertices = getVertexListAsFloat();
507
508 // If there isn't an unmanaged array allocated yet, do it now
509 if (m_indicesPtr == IntPtr.Zero)
510 indexes = getIndexListAsInt();
511
512 pinMemory();
513
514 float x, y, z;
515
516 if (m_bdata.m_centroidDiv > 0)
517 {
518 m_obboffset = new Vector3(m_bdata.m_centroid.X / m_bdata.m_centroidDiv, m_bdata.m_centroid.Y / m_bdata.m_centroidDiv, m_bdata.m_centroid.Z / m_bdata.m_centroidDiv);
519 x = (m_bdata.m_obbXmax - m_bdata.m_obbXmin) * 0.5f;
520 if(x < 0.0005f)
521 x = 0.0005f;
522 y = (m_bdata.m_obbYmax - m_bdata.m_obbYmin) * 0.5f;
523 if(y < 0.0005f)
524 y = 0.0005f;
525 z = (m_bdata.m_obbZmax - m_bdata.m_obbZmin) * 0.5f;
526 if(z < 0.0005f)
527 z = 0.0005f;
528 }
529
530 else
531 {
532 m_obboffset = Vector3.Zero;
533 x = 0.5f;
534 y = 0.5f;
535 z = 0.5f;
536 }
537
538 m_obb = new Vector3(x, y, z);
539
540 releaseBuildingMeshData();
541 }
542 public bool ToStream(Stream st)
543 {
544 if (m_indicesPtr == IntPtr.Zero || m_verticesPtr == IntPtr.Zero)
545 return false;
546
547 BinaryWriter bw = new BinaryWriter(st);
548 bool ok = true;
549
550 try
551 {
552
553 bw.Write(m_vertexCount);
554 bw.Write(m_indexCount);
555
556 for (int i = 0; i < 3 * m_vertexCount; i++)
557 bw.Write(vertices[i]);
558 for (int i = 0; i < m_indexCount; i++)
559 bw.Write(indexes[i]);
560 bw.Write(m_obb.X);
561 bw.Write(m_obb.Y);
562 bw.Write(m_obb.Z);
563 bw.Write(m_obboffset.X);
564 bw.Write(m_obboffset.Y);
565 bw.Write(m_obboffset.Z);
566 }
567 catch
568 {
569 ok = false;
570 }
571
572 if (bw != null)
573 {
574 bw.Flush();
575 bw.Close();
576 }
577
578 return ok;
579 }
580
581 public static Mesh FromStream(Stream st, AMeshKey key)
582 {
583 Mesh mesh = new Mesh();
584 mesh.releaseBuildingMeshData();
585
586 BinaryReader br = new BinaryReader(st);
587
588 bool ok = true;
589 try
590 {
591 mesh.m_vertexCount = br.ReadInt32();
592 mesh.m_indexCount = br.ReadInt32();
593
594 int n = 3 * mesh.m_vertexCount;
595 mesh.vertices = new float[n];
596 for (int i = 0; i < n; i++)
597 mesh.vertices[i] = br.ReadSingle();
598
599 mesh.indexes = new int[mesh.m_indexCount];
600 for (int i = 0; i < mesh.m_indexCount; i++)
601 mesh.indexes[i] = br.ReadInt32();
602
603 mesh.m_obb.X = br.ReadSingle();
604 mesh.m_obb.Y = br.ReadSingle();
605 mesh.m_obb.Z = br.ReadSingle();
606
607 mesh.m_obboffset.X = br.ReadSingle();
608 mesh.m_obboffset.Y = br.ReadSingle();
609 mesh.m_obboffset.Z = br.ReadSingle();
610 }
611 catch
612 {
613 ok = false;
614 }
615
616 br.Close();
617
618 if (ok)
619 {
620 mesh.pinMemory();
621
622 mesh.Key = key;
623 mesh.RefCount = 1;
624
625 return mesh;
626 }
627
628 mesh.vertices = null;
629 mesh.indexes = null;
630 return null;
631 }
632 }
633}
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
new file mode 100644
index 0000000..a6e303a
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
@@ -0,0 +1,1465 @@
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//#define SPAM
28
29using System;
30using System.Collections.Generic;
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.PhysicsModules.SharedBase;
35using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using System.Drawing;
39using System.Drawing.Imaging;
40using System.IO.Compression;
41using PrimMesher;
42using log4net;
43using Nini.Config;
44using System.Reflection;
45using System.IO;
46using System.Runtime.Serialization;
47using System.Runtime.Serialization.Formatters.Binary;
48
49using Mono.Addins;
50
51namespace OpenSim.Region.PhysicsModule.ubODEMeshing
52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ubODEMeshmerizer")]
54 public class ubMeshmerizer : IMesher, INonSharedRegionModule
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57
58 // Setting baseDir to a path will enable the dumping of raw files
59 // raw files can be imported by blender so a visual inspection of the results can be done
60
61 private bool m_Enabled = false;
62
63 public object diskLock = new object();
64
65 public bool doMeshFileCache = true;
66
67 public string cachePath = "MeshCache";
68 public TimeSpan CacheExpire;
69 public bool doCacheExpire = true;
70
71// const string baseDir = "rawFiles";
72 private const string baseDir = null; //"rawFiles";
73
74 private bool useMeshiesPhysicsMesh = false;
75
76 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
77
78 private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
79 private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
80
81 #region INonSharedRegionModule
82 public string Name
83 {
84 get { return "ubODEMeshmerizer"; }
85 }
86
87 public Type ReplaceableInterface
88 {
89 get { return null; }
90 }
91
92 public void Initialise(IConfigSource config)
93 {
94 IConfig start_config = config.Configs["Startup"];
95
96 string mesher = start_config.GetString("meshing", string.Empty);
97 if (mesher == Name)
98 {
99 float fcache = 48.0f;
100 // float fcache = 0.02f;
101
102 IConfig mesh_config = config.Configs["Mesh"];
103 if (mesh_config != null)
104 {
105 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
106 if (useMeshiesPhysicsMesh)
107 {
108 doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache);
109 cachePath = mesh_config.GetString("MeshFileCachePath", cachePath);
110 fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache);
111 doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire);
112 }
113 else
114 {
115 doMeshFileCache = false;
116 doCacheExpire = false;
117 }
118
119 m_Enabled = true;
120 }
121
122 CacheExpire = TimeSpan.FromHours(fcache);
123
124 }
125 }
126
127 public void Close()
128 {
129 }
130
131 public void AddRegion(Scene scene)
132 {
133 if (!m_Enabled)
134 return;
135
136 scene.RegisterModuleInterface<IMesher>(this);
137 }
138
139 public void RemoveRegion(Scene scene)
140 {
141 if (!m_Enabled)
142 return;
143
144 scene.UnregisterModuleInterface<IMesher>(this);
145 }
146
147 public void RegionLoaded(Scene scene)
148 {
149 if (!m_Enabled)
150 return;
151 }
152
153 #endregion
154
155 /// <summary>
156 /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may
157 /// be useful as a backup proxy when level of detail is not needed or when more complex meshes fail
158 /// for some reason
159 /// </summary>
160 /// <param name="minX"></param>
161 /// <param name="maxX"></param>
162 /// <param name="minY"></param>
163 /// <param name="maxY"></param>
164 /// <param name="minZ"></param>
165 /// <param name="maxZ"></param>
166 /// <returns></returns>
167 private static Mesh CreateSimpleBoxMesh(float minX, float maxX, float minY, float maxY, float minZ, float maxZ)
168 {
169 Mesh box = new Mesh();
170 List<Vertex> vertices = new List<Vertex>();
171 // bottom
172
173 vertices.Add(new Vertex(minX, maxY, minZ));
174 vertices.Add(new Vertex(maxX, maxY, minZ));
175 vertices.Add(new Vertex(maxX, minY, minZ));
176 vertices.Add(new Vertex(minX, minY, minZ));
177
178 box.Add(new Triangle(vertices[0], vertices[1], vertices[2]));
179 box.Add(new Triangle(vertices[0], vertices[2], vertices[3]));
180
181 // top
182
183 vertices.Add(new Vertex(maxX, maxY, maxZ));
184 vertices.Add(new Vertex(minX, maxY, maxZ));
185 vertices.Add(new Vertex(minX, minY, maxZ));
186 vertices.Add(new Vertex(maxX, minY, maxZ));
187
188 box.Add(new Triangle(vertices[4], vertices[5], vertices[6]));
189 box.Add(new Triangle(vertices[4], vertices[6], vertices[7]));
190
191 // sides
192
193 box.Add(new Triangle(vertices[5], vertices[0], vertices[3]));
194 box.Add(new Triangle(vertices[5], vertices[3], vertices[6]));
195
196 box.Add(new Triangle(vertices[1], vertices[0], vertices[5]));
197 box.Add(new Triangle(vertices[1], vertices[5], vertices[4]));
198
199 box.Add(new Triangle(vertices[7], vertices[1], vertices[4]));
200 box.Add(new Triangle(vertices[7], vertices[2], vertices[1]));
201
202 box.Add(new Triangle(vertices[3], vertices[2], vertices[7]));
203 box.Add(new Triangle(vertices[3], vertices[7], vertices[6]));
204
205 return box;
206 }
207
208 /// <summary>
209 /// Creates a simple bounding box mesh for a complex input mesh
210 /// </summary>
211 /// <param name="meshIn"></param>
212 /// <returns></returns>
213 private static Mesh CreateBoundingBoxMesh(Mesh meshIn)
214 {
215 float minX = float.MaxValue;
216 float maxX = float.MinValue;
217 float minY = float.MaxValue;
218 float maxY = float.MinValue;
219 float minZ = float.MaxValue;
220 float maxZ = float.MinValue;
221
222 foreach (Vector3 v in meshIn.getVertexList())
223 {
224 if (v.X < minX) minX = v.X;
225 if (v.Y < minY) minY = v.Y;
226 if (v.Z < minZ) minZ = v.Z;
227
228 if (v.X > maxX) maxX = v.X;
229 if (v.Y > maxY) maxY = v.Y;
230 if (v.Z > maxZ) maxZ = v.Z;
231 }
232
233 return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ);
234 }
235
236 private void ReportPrimError(string message, string primName, PrimMesh primMesh)
237 {
238 m_log.Error(message);
239 m_log.Error("\nPrim Name: " + primName);
240 m_log.Error("****** PrimMesh Parameters ******\n" + primMesh.ParamsToDisplayString());
241 }
242
243 /// <summary>
244 /// Add a submesh to an existing list of coords and faces.
245 /// </summary>
246 /// <param name="subMeshData"></param>
247 /// <param name="size">Size of entire object</param>
248 /// <param name="coords"></param>
249 /// <param name="faces"></param>
250 private void AddSubMesh(OSDMap subMeshData, List<Coord> coords, List<Face> faces)
251 {
252 // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap));
253
254 // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level
255 // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no
256 // geometry for this submesh.
257 if (subMeshData.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshData["NoGeometry"]))
258 return;
259
260 OpenMetaverse.Vector3 posMax;
261 OpenMetaverse.Vector3 posMin;
262 if (subMeshData.ContainsKey("PositionDomain"))
263 {
264 posMax = ((OSDMap)subMeshData["PositionDomain"])["Max"].AsVector3();
265 posMin = ((OSDMap)subMeshData["PositionDomain"])["Min"].AsVector3();
266 }
267 else
268 {
269 posMax = new Vector3(0.5f, 0.5f, 0.5f);
270 posMin = new Vector3(-0.5f, -0.5f, -0.5f);
271 }
272
273 ushort faceIndexOffset = (ushort)coords.Count;
274
275 byte[] posBytes = subMeshData["Position"].AsBinary();
276 for (int i = 0; i < posBytes.Length; i += 6)
277 {
278 ushort uX = Utils.BytesToUInt16(posBytes, i);
279 ushort uY = Utils.BytesToUInt16(posBytes, i + 2);
280 ushort uZ = Utils.BytesToUInt16(posBytes, i + 4);
281
282 Coord c = new Coord(
283 Utils.UInt16ToFloat(uX, posMin.X, posMax.X),
284 Utils.UInt16ToFloat(uY, posMin.Y, posMax.Y),
285 Utils.UInt16ToFloat(uZ, posMin.Z, posMax.Z));
286
287 coords.Add(c);
288 }
289
290 byte[] triangleBytes = subMeshData["TriangleList"].AsBinary();
291 for (int i = 0; i < triangleBytes.Length; i += 6)
292 {
293 ushort v1 = (ushort)(Utils.BytesToUInt16(triangleBytes, i) + faceIndexOffset);
294 ushort v2 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 2) + faceIndexOffset);
295 ushort v3 = (ushort)(Utils.BytesToUInt16(triangleBytes, i + 4) + faceIndexOffset);
296 Face f = new Face(v1, v2, v3);
297 faces.Add(f);
298 }
299 }
300
301 /// <summary>
302 /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type.
303 /// </summary>
304 /// <param name="primName"></param>
305 /// <param name="primShape"></param>
306 /// <param name="size"></param>
307 /// <param name="lod"></param>
308 /// <returns></returns>
309 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, float lod, bool convex)
310 {
311// m_log.DebugFormat(
312// "[MESH]: Creating physics proxy for {0}, shape {1}",
313// primName, (OpenMetaverse.SculptType)primShape.SculptType);
314
315 List<Coord> coords;
316 List<Face> faces;
317
318 if (primShape.SculptEntry)
319 {
320 if (((OpenMetaverse.SculptType)primShape.SculptType) == SculptType.Mesh)
321 {
322 if (!useMeshiesPhysicsMesh)
323 return null;
324
325 if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex))
326 return null;
327 }
328 else
329 {
330 if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces))
331 return null;
332 }
333 }
334 else
335 {
336 if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, out coords, out faces))
337 return null;
338 }
339
340
341 int numCoords = coords.Count;
342 int numFaces = faces.Count;
343
344 Mesh mesh = new Mesh();
345 // Add the corresponding triangles to the mesh
346 for (int i = 0; i < numFaces; i++)
347 {
348 Face f = faces[i];
349 mesh.Add(new Triangle(coords[f.v1].X, coords[f.v1].Y, coords[f.v1].Z,
350 coords[f.v2].X, coords[f.v2].Y, coords[f.v2].Z,
351 coords[f.v3].X, coords[f.v3].Y, coords[f.v3].Z));
352 }
353
354 coords.Clear();
355 faces.Clear();
356
357 if(mesh.numberVertices() < 3 || mesh.numberTriangles() < 1)
358 {
359 m_log.ErrorFormat("[MESH]: invalid degenerated mesh for prim " + primName + " ignored");
360 return null;
361 }
362
363 primShape.SculptData = Utils.EmptyBytes;
364
365 return mesh;
366 }
367
368 /// <summary>
369 /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim.
370 /// </summary>
371 /// <param name="primName"></param>
372 /// <param name="primShape"></param>
373 /// <param name="size"></param>
374 /// <param name="coords">Coords are added to this list by the method.</param>
375 /// <param name="faces">Faces are added to this list by the method.</param>
376 /// <returns>true if coords and faces were successfully generated, false if not</returns>
377 private bool GenerateCoordsAndFacesFromPrimMeshData(
378 string primName, PrimitiveBaseShape primShape, out List<Coord> coords, out List<Face> faces, bool convex)
379 {
380// m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
381
382 bool usemesh = false;
383
384 coords = new List<Coord>();
385 faces = new List<Face>();
386 OSD meshOsd = null;
387
388 if (primShape.SculptData.Length <= 0)
389 {
390// m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
391 return false;
392 }
393
394 long start = 0;
395 using (MemoryStream data = new MemoryStream(primShape.SculptData))
396 {
397 try
398 {
399 OSD osd = OSDParser.DeserializeLLSDBinary(data);
400 if (osd is OSDMap)
401 meshOsd = (OSDMap)osd;
402 else
403 {
404 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
405 return false;
406 }
407 }
408 catch (Exception e)
409 {
410 m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString());
411 }
412
413 start = data.Position;
414 }
415
416 if (meshOsd is OSDMap)
417 {
418 OSDMap physicsParms = null;
419 OSDMap map = (OSDMap)meshOsd;
420
421 if (!convex)
422 {
423 if (map.ContainsKey("physics_shape"))
424 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
425 else if (map.ContainsKey("physics_mesh"))
426 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
427
428 if (physicsParms != null)
429 usemesh = true;
430 }
431
432 if(!usemesh && (map.ContainsKey("physics_convex")))
433 physicsParms = (OSDMap)map["physics_convex"];
434
435
436 if (physicsParms == null)
437 {
438 m_log.Warn("[MESH]: unknown mesh type");
439 return false;
440 }
441
442 int physOffset = physicsParms["offset"].AsInteger() + (int)start;
443 int physSize = physicsParms["size"].AsInteger();
444
445 if (physOffset < 0 || physSize == 0)
446 return false; // no mesh data in asset
447
448 OSD decodedMeshOsd = new OSD();
449 byte[] meshBytes = new byte[physSize];
450 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
451
452 try
453 {
454 using (MemoryStream inMs = new MemoryStream(meshBytes))
455 {
456 using (MemoryStream outMs = new MemoryStream())
457 {
458 using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress))
459 {
460 byte[] readBuffer = new byte[2048];
461 inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header
462 int readLen = 0;
463
464 while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
465 outMs.Write(readBuffer, 0, readLen);
466
467 outMs.Flush();
468 outMs.Seek(0, SeekOrigin.Begin);
469
470 byte[] decompressedBuf = outMs.GetBuffer();
471
472 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
473 }
474 }
475 }
476 }
477 catch (Exception e)
478 {
479 m_log.Error("[MESH]: exception decoding physical mesh prim " + primName +" : " + e.ToString());
480 return false;
481 }
482
483 if (usemesh)
484 {
485 OSDArray decodedMeshOsdArray = null;
486
487 // physics_shape is an array of OSDMaps, one for each submesh
488 if (decodedMeshOsd is OSDArray)
489 {
490// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
491
492 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
493 foreach (OSD subMeshOsd in decodedMeshOsdArray)
494 {
495 if (subMeshOsd is OSDMap)
496 AddSubMesh(subMeshOsd as OSDMap, coords, faces);
497 }
498 }
499 }
500 else
501 {
502 OSDMap cmap = (OSDMap)decodedMeshOsd;
503 if (cmap == null)
504 return false;
505
506 byte[] data;
507
508 List<float3> vs = new List<float3>();
509 PHullResult hullr = new PHullResult();
510 float3 f3;
511 Coord c;
512 Face f;
513 Vector3 range;
514 Vector3 min;
515
516 const float invMaxU16 = 1.0f / 65535f;
517 int t1;
518 int t2;
519 int t3;
520 int i;
521 int nverts;
522 int nindexs;
523
524 if (cmap.ContainsKey("Max"))
525 range = cmap["Max"].AsVector3();
526 else
527 range = new Vector3(0.5f, 0.5f, 0.5f);
528
529 if (cmap.ContainsKey("Min"))
530 min = cmap["Min"].AsVector3();
531 else
532 min = new Vector3(-0.5f, -0.5f, -0.5f);
533
534 range = range - min;
535 range *= invMaxU16;
536
537 if (!convex && cmap.ContainsKey("HullList") && cmap.ContainsKey("Positions"))
538 {
539 List<int> hsizes = new List<int>();
540 int totalpoints = 0;
541 data = cmap["HullList"].AsBinary();
542 for (i = 0; i < data.Length; i++)
543 {
544 t1 = data[i];
545 if (t1 == 0)
546 t1 = 256;
547 totalpoints += t1;
548 hsizes.Add(t1);
549 }
550
551 data = cmap["Positions"].AsBinary();
552 int ptr = 0;
553 int vertsoffset = 0;
554
555 if (totalpoints == data.Length / 6) // 2 bytes per coord, 3 coords per point
556 {
557 foreach (int hullsize in hsizes)
558 {
559 for (i = 0; i < hullsize; i++ )
560 {
561 t1 = data[ptr++];
562 t1 += data[ptr++] << 8;
563 t2 = data[ptr++];
564 t2 += data[ptr++] << 8;
565 t3 = data[ptr++];
566 t3 += data[ptr++] << 8;
567
568 f3 = new float3((t1 * range.X + min.X),
569 (t2 * range.Y + min.Y),
570 (t3 * range.Z + min.Z));
571 vs.Add(f3);
572 }
573
574 if(hullsize <3)
575 {
576 vs.Clear();
577 continue;
578 }
579
580 if (hullsize <5)
581 {
582 foreach (float3 point in vs)
583 {
584 c.X = point.x;
585 c.Y = point.y;
586 c.Z = point.z;
587 coords.Add(c);
588 }
589 f = new Face(vertsoffset, vertsoffset + 1, vertsoffset + 2);
590 faces.Add(f);
591
592 if (hullsize == 4)
593 {
594 // not sure about orientation..
595 f = new Face(vertsoffset, vertsoffset + 2, vertsoffset + 3);
596 faces.Add(f);
597 f = new Face(vertsoffset, vertsoffset + 3, vertsoffset + 1);
598 faces.Add(f);
599 f = new Face(vertsoffset + 3, vertsoffset + 2, vertsoffset + 1);
600 faces.Add(f);
601 }
602 vertsoffset += vs.Count;
603 vs.Clear();
604 continue;
605 }
606
607 if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f))
608 {
609 vs.Clear();
610 continue;
611 }
612
613 nverts = hullr.Vertices.Count;
614 nindexs = hullr.Indices.Count;
615
616 if (nindexs % 3 != 0)
617 {
618 vs.Clear();
619 continue;
620 }
621
622 for (i = 0; i < nverts; i++)
623 {
624 c.X = hullr.Vertices[i].x;
625 c.Y = hullr.Vertices[i].y;
626 c.Z = hullr.Vertices[i].z;
627 coords.Add(c);
628 }
629
630 for (i = 0; i < nindexs; i += 3)
631 {
632 t1 = hullr.Indices[i];
633 if (t1 > nverts)
634 break;
635 t2 = hullr.Indices[i + 1];
636 if (t2 > nverts)
637 break;
638 t3 = hullr.Indices[i + 2];
639 if (t3 > nverts)
640 break;
641 f = new Face(vertsoffset + t1, vertsoffset + t2, vertsoffset + t3);
642 faces.Add(f);
643 }
644 vertsoffset += nverts;
645 vs.Clear();
646 }
647 }
648 if (coords.Count > 0 && faces.Count > 0)
649 return true;
650 }
651
652 vs.Clear();
653
654 if (cmap.ContainsKey("BoundingVerts"))
655 {
656 data = cmap["BoundingVerts"].AsBinary();
657
658 for (i = 0; i < data.Length; )
659 {
660 t1 = data[i++];
661 t1 += data[i++] << 8;
662 t2 = data[i++];
663 t2 += data[i++] << 8;
664 t3 = data[i++];
665 t3 += data[i++] << 8;
666
667 f3 = new float3((t1 * range.X + min.X),
668 (t2 * range.Y + min.Y),
669 (t3 * range.Z + min.Z));
670 vs.Add(f3);
671 }
672
673 if (vs.Count < 3)
674 {
675 vs.Clear();
676 return false;
677 }
678
679 if (vs.Count < 5)
680 {
681 foreach (float3 point in vs)
682 {
683 c.X = point.x;
684 c.Y = point.y;
685 c.Z = point.z;
686 coords.Add(c);
687 }
688 f = new Face(0, 1, 2);
689 faces.Add(f);
690
691 if (vs.Count == 4)
692 {
693 f = new Face(0, 2, 3);
694 faces.Add(f);
695 f = new Face(0, 3, 1);
696 faces.Add(f);
697 f = new Face( 3, 2, 1);
698 faces.Add(f);
699 }
700 vs.Clear();
701 return true;
702 }
703
704 if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f))
705 return false;
706
707 nverts = hullr.Vertices.Count;
708 nindexs = hullr.Indices.Count;
709
710 if (nindexs % 3 != 0)
711 return false;
712
713 for (i = 0; i < nverts; i++)
714 {
715 c.X = hullr.Vertices[i].x;
716 c.Y = hullr.Vertices[i].y;
717 c.Z = hullr.Vertices[i].z;
718 coords.Add(c);
719 }
720 for (i = 0; i < nindexs; i += 3)
721 {
722 t1 = hullr.Indices[i];
723 if (t1 > nverts)
724 break;
725 t2 = hullr.Indices[i + 1];
726 if (t2 > nverts)
727 break;
728 t3 = hullr.Indices[i + 2];
729 if (t3 > nverts)
730 break;
731 f = new Face(t1, t2, t3);
732 faces.Add(f);
733 }
734
735 if (coords.Count > 0 && faces.Count > 0)
736 return true;
737 }
738 else
739 return false;
740 }
741 }
742
743 return true;
744 }
745
746 /// <summary>
747 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim.
748 /// </summary>
749 /// <param name="primName"></param>
750 /// <param name="primShape"></param>
751 /// <param name="size"></param>
752 /// <param name="lod"></param>
753 /// <param name="coords">Coords are added to this list by the method.</param>
754 /// <param name="faces">Faces are added to this list by the method.</param>
755 /// <returns>true if coords and faces were successfully generated, false if not</returns>
756 private bool GenerateCoordsAndFacesFromPrimSculptData(
757 string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
758 {
759 coords = new List<Coord>();
760 faces = new List<Face>();
761 PrimMesher.SculptMesh sculptMesh;
762 Image idata = null;
763
764 if (primShape.SculptData == null || primShape.SculptData.Length == 0)
765 return false;
766
767 try
768 {
769 OpenMetaverse.Imaging.ManagedImage unusedData;
770 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
771
772 unusedData = null;
773
774 if (idata == null)
775 {
776 // In some cases it seems that the decode can return a null bitmap without throwing
777 // an exception
778 m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
779 return false;
780 }
781 }
782 catch (DllNotFoundException)
783 {
784 m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed. Often times this is because of an old version of GLIBC. You must have version 2.4 or above!");
785 return false;
786 }
787 catch (IndexOutOfRangeException)
788 {
789 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
790 return false;
791 }
792 catch (Exception ex)
793 {
794 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
795 return false;
796 }
797
798 PrimMesher.SculptMesh.SculptType sculptType;
799 // remove mirror and invert bits
800 OpenMetaverse.SculptType pbsSculptType = ((OpenMetaverse.SculptType)(primShape.SculptType & 0x3f));
801 switch (pbsSculptType)
802 {
803 case OpenMetaverse.SculptType.Cylinder:
804 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
805 break;
806 case OpenMetaverse.SculptType.Plane:
807 sculptType = PrimMesher.SculptMesh.SculptType.plane;
808 break;
809 case OpenMetaverse.SculptType.Torus:
810 sculptType = PrimMesher.SculptMesh.SculptType.torus;
811 break;
812 case OpenMetaverse.SculptType.Sphere:
813 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
814 break;
815 default:
816 sculptType = PrimMesher.SculptMesh.SculptType.plane;
817 break;
818 }
819
820 bool mirror = ((primShape.SculptType & 128) != 0);
821 bool invert = ((primShape.SculptType & 64) != 0);
822
823 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, mirror, invert);
824
825 idata.Dispose();
826
827// sculptMesh.DumpRaw(baseDir, primName, "primMesh");
828
829 coords = sculptMesh.coords;
830 faces = sculptMesh.faces;
831
832 return true;
833 }
834
835 /// <summary>
836 /// Generate the co-ords and faces necessary to construct a mesh from the shape data the accompanies a prim.
837 /// </summary>
838 /// <param name="primName"></param>
839 /// <param name="primShape"></param>
840 /// <param name="size"></param>
841 /// <param name="coords">Coords are added to this list by the method.</param>
842 /// <param name="faces">Faces are added to this list by the method.</param>
843 /// <returns>true if coords and faces were successfully generated, false if not</returns>
844 private bool GenerateCoordsAndFacesFromPrimShapeData(
845 string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
846 {
847 PrimMesh primMesh;
848 coords = new List<Coord>();
849 faces = new List<Face>();
850
851 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
852 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
853 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
854 float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
855 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
856 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
857
858 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
859 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
860
861 if (profileBegin < 0.0f)
862 profileBegin = 0.0f;
863
864 if (profileEnd < 0.02f)
865 profileEnd = 0.02f;
866 else if (profileEnd > 1.0f)
867 profileEnd = 1.0f;
868
869 if (profileBegin >= profileEnd)
870 profileBegin = profileEnd - 0.02f;
871
872 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
873 if (profileHollow > 0.95f)
874 profileHollow = 0.95f;
875
876 int sides = 4;
877 LevelOfDetail iLOD = (LevelOfDetail)lod;
878 byte profshape = (byte)(primShape.ProfileCurve & 0x07);
879
880 if (profshape == (byte)ProfileShape.EquilateralTriangle
881 || profshape == (byte)ProfileShape.IsometricTriangle
882 || profshape == (byte)ProfileShape.RightTriangle)
883 sides = 3;
884 else if (profshape == (byte)ProfileShape.Circle)
885 {
886 switch (iLOD)
887 {
888 case LevelOfDetail.High: sides = 24; break;
889 case LevelOfDetail.Medium: sides = 12; break;
890 case LevelOfDetail.Low: sides = 6; break;
891 case LevelOfDetail.VeryLow: sides = 3; break;
892 default: sides = 24; break;
893 }
894 }
895 else if (profshape == (byte)ProfileShape.HalfCircle)
896 { // half circle, prim is a sphere
897 switch (iLOD)
898 {
899 case LevelOfDetail.High: sides = 24; break;
900 case LevelOfDetail.Medium: sides = 12; break;
901 case LevelOfDetail.Low: sides = 6; break;
902 case LevelOfDetail.VeryLow: sides = 3; break;
903 default: sides = 24; break;
904 }
905
906 profileBegin = 0.5f * profileBegin + 0.5f;
907 profileEnd = 0.5f * profileEnd + 0.5f;
908 }
909
910 int hollowSides = sides;
911 if (primShape.HollowShape == HollowShape.Circle)
912 {
913 switch (iLOD)
914 {
915 case LevelOfDetail.High: hollowSides = 24; break;
916 case LevelOfDetail.Medium: hollowSides = 12; break;
917 case LevelOfDetail.Low: hollowSides = 6; break;
918 case LevelOfDetail.VeryLow: hollowSides = 3; break;
919 default: hollowSides = 24; break;
920 }
921 }
922 else if (primShape.HollowShape == HollowShape.Square)
923 hollowSides = 4;
924 else if (primShape.HollowShape == HollowShape.Triangle)
925 {
926 if (profshape == (byte)ProfileShape.HalfCircle)
927 hollowSides = 6;
928 else
929 hollowSides = 3;
930 }
931
932 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
933
934 if (primMesh.errorMessage != null)
935 if (primMesh.errorMessage.Length > 0)
936 m_log.Error("[ERROR] " + primMesh.errorMessage);
937
938 primMesh.topShearX = pathShearX;
939 primMesh.topShearY = pathShearY;
940 primMesh.pathCutBegin = pathBegin;
941 primMesh.pathCutEnd = pathEnd;
942
943 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible)
944 {
945 primMesh.twistBegin = (primShape.PathTwistBegin * 18) / 10;
946 primMesh.twistEnd = (primShape.PathTwist * 18) / 10;
947 primMesh.taperX = pathScaleX;
948 primMesh.taperY = pathScaleY;
949
950#if SPAM
951 m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
952#endif
953 try
954 {
955 primMesh.ExtrudeLinear();
956 }
957 catch (Exception ex)
958 {
959 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
960 return false;
961 }
962 }
963 else
964 {
965 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f;
966 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f;
967 primMesh.radius = 0.01f * primShape.PathRadiusOffset;
968 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions;
969 primMesh.skew = 0.01f * primShape.PathSkew;
970 primMesh.twistBegin = (primShape.PathTwistBegin * 36) / 10;
971 primMesh.twistEnd = (primShape.PathTwist * 36) / 10;
972 primMesh.taperX = primShape.PathTaperX * 0.01f;
973 primMesh.taperY = primShape.PathTaperY * 0.01f;
974
975#if SPAM
976 m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString());
977#endif
978 try
979 {
980 primMesh.ExtrudeCircular();
981 }
982 catch (Exception ex)
983 {
984 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
985 return false;
986 }
987 }
988
989// primMesh.DumpRaw(baseDir, primName, "primMesh");
990
991 coords = primMesh.coords;
992 faces = primMesh.faces;
993
994 return true;
995 }
996
997 public AMeshKey GetMeshUniqueKey(PrimitiveBaseShape primShape, Vector3 size, byte lod, bool convex)
998 {
999 AMeshKey key = new AMeshKey();
1000 Byte[] someBytes;
1001
1002 key.hashB = 5181;
1003 key.hashC = 5181;
1004 ulong hash = 5381;
1005
1006 if (primShape.SculptEntry)
1007 {
1008 key.uuid = primShape.SculptTexture;
1009 key.hashC = mdjb2(key.hashC, primShape.SculptType);
1010 key.hashC = mdjb2(key.hashC, primShape.PCode);
1011 }
1012 else
1013 {
1014 hash = mdjb2(hash, primShape.PathCurve);
1015 hash = mdjb2(hash, (byte)primShape.HollowShape);
1016 hash = mdjb2(hash, (byte)primShape.ProfileShape);
1017 hash = mdjb2(hash, primShape.PathBegin);
1018 hash = mdjb2(hash, primShape.PathEnd);
1019 hash = mdjb2(hash, primShape.PathScaleX);
1020 hash = mdjb2(hash, primShape.PathScaleY);
1021 hash = mdjb2(hash, primShape.PathShearX);
1022 key.hashA = hash;
1023 hash = key.hashB;
1024 hash = mdjb2(hash, primShape.PathShearY);
1025 hash = mdjb2(hash, (byte)primShape.PathTwist);
1026 hash = mdjb2(hash, (byte)primShape.PathTwistBegin);
1027 hash = mdjb2(hash, (byte)primShape.PathRadiusOffset);
1028 hash = mdjb2(hash, (byte)primShape.PathTaperX);
1029 hash = mdjb2(hash, (byte)primShape.PathTaperY);
1030 hash = mdjb2(hash, primShape.PathRevolutions);
1031 hash = mdjb2(hash, (byte)primShape.PathSkew);
1032 hash = mdjb2(hash, primShape.ProfileBegin);
1033 hash = mdjb2(hash, primShape.ProfileEnd);
1034 hash = mdjb2(hash, primShape.ProfileHollow);
1035 hash = mdjb2(hash, primShape.PCode);
1036 key.hashB = hash;
1037 }
1038
1039 hash = key.hashC;
1040
1041 hash = mdjb2(hash, lod);
1042
1043 if (size == m_MeshUnitSize)
1044 {
1045 hash = hash << 8;
1046 hash |= 8;
1047 }
1048 else
1049 {
1050 someBytes = size.GetBytes();
1051 for (int i = 0; i < someBytes.Length; i++)
1052 hash = mdjb2(hash, someBytes[i]);
1053 hash = hash << 8;
1054 }
1055
1056 if (convex)
1057 hash |= 4;
1058
1059 if (primShape.SculptEntry)
1060 {
1061 hash |= 1;
1062 if (primShape.SculptType == (byte)SculptType.Mesh)
1063 hash |= 2;
1064 }
1065
1066 key.hashC = hash;
1067
1068 return key;
1069 }
1070
1071 private ulong mdjb2(ulong hash, byte c)
1072 {
1073 return ((hash << 5) + hash) + (ulong)c;
1074 }
1075
1076 private ulong mdjb2(ulong hash, ushort c)
1077 {
1078 hash = ((hash << 5) + hash) + (ulong)((byte)c);
1079 return ((hash << 5) + hash) + (ulong)(c >> 8);
1080 }
1081
1082 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
1083 {
1084 return CreateMesh(primName, primShape, size, lod, false,false,false);
1085 }
1086
1087 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical)
1088 {
1089 return CreateMesh(primName, primShape, size, lod, false,false,false);
1090 }
1091
1092 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool shouldCache, bool convex, bool forOde)
1093 {
1094 return CreateMesh(primName, primShape, size, lod, false, false, false);
1095 }
1096
1097 public IMesh GetMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex)
1098 {
1099 Mesh mesh = null;
1100
1101 if (size.X < 0.01f) size.X = 0.01f;
1102 if (size.Y < 0.01f) size.Y = 0.01f;
1103 if (size.Z < 0.01f) size.Z = 0.01f;
1104
1105 AMeshKey key = GetMeshUniqueKey(primShape, size, (byte)lod, convex);
1106 lock (m_uniqueMeshes)
1107 {
1108 m_uniqueMeshes.TryGetValue(key, out mesh);
1109
1110 if (mesh != null)
1111 {
1112 mesh.RefCount++;
1113 return mesh;
1114 }
1115
1116 // try to find a identical mesh on meshs recently released
1117 lock (m_uniqueReleasedMeshes)
1118 {
1119 m_uniqueReleasedMeshes.TryGetValue(key, out mesh);
1120 if (mesh != null)
1121 {
1122 m_uniqueReleasedMeshes.Remove(key);
1123 try
1124 {
1125 m_uniqueMeshes.Add(key, mesh);
1126 }
1127 catch { }
1128 mesh.RefCount = 1;
1129 return mesh;
1130 }
1131 }
1132 }
1133 return null;
1134 }
1135
1136 private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
1137
1138 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
1139 {
1140#if SPAM
1141 m_log.DebugFormat("[MESH]: Creating mesh for {0}", primName);
1142#endif
1143
1144 Mesh mesh = null;
1145
1146 if (size.X < 0.01f) size.X = 0.01f;
1147 if (size.Y < 0.01f) size.Y = 0.01f;
1148 if (size.Z < 0.01f) size.Z = 0.01f;
1149
1150 // try to find a identical mesh on meshs in use
1151
1152 AMeshKey key = GetMeshUniqueKey(primShape,size,(byte)lod, convex);
1153
1154 lock (m_uniqueMeshes)
1155 {
1156 m_uniqueMeshes.TryGetValue(key, out mesh);
1157
1158 if (mesh != null)
1159 {
1160 mesh.RefCount++;
1161 return mesh;
1162 }
1163
1164 // try to find a identical mesh on meshs recently released
1165 lock (m_uniqueReleasedMeshes)
1166 {
1167 m_uniqueReleasedMeshes.TryGetValue(key, out mesh);
1168 if (mesh != null)
1169 {
1170 m_uniqueReleasedMeshes.Remove(key);
1171 try
1172 {
1173 m_uniqueMeshes.Add(key, mesh);
1174 }
1175 catch { }
1176 mesh.RefCount = 1;
1177 return mesh;
1178 }
1179 }
1180 }
1181
1182 Mesh UnitMesh = null;
1183 AMeshKey unitKey = GetMeshUniqueKey(primShape, m_MeshUnitSize, (byte)lod, convex);
1184
1185 lock (m_uniqueReleasedMeshes)
1186 {
1187 m_uniqueReleasedMeshes.TryGetValue(unitKey, out UnitMesh);
1188 if (UnitMesh != null)
1189 {
1190 UnitMesh.RefCount = 1;
1191 }
1192 }
1193
1194 if (UnitMesh == null && primShape.SculptEntry && doMeshFileCache)
1195 UnitMesh = GetFromFileCache(unitKey);
1196
1197 if (UnitMesh == null)
1198 {
1199 UnitMesh = CreateMeshFromPrimMesher(primName, primShape, lod, convex);
1200
1201 if (UnitMesh == null)
1202 return null;
1203
1204 UnitMesh.DumpRaw(baseDir, unitKey.ToString(), "Z");
1205
1206 if (forOde)
1207 {
1208 // force pinned mem allocation
1209 UnitMesh.PrepForOde();
1210 }
1211 else
1212 UnitMesh.TrimExcess();
1213
1214 UnitMesh.Key = unitKey;
1215 UnitMesh.RefCount = 1;
1216
1217 if (doMeshFileCache && primShape.SculptEntry)
1218 StoreToFileCache(unitKey, UnitMesh);
1219
1220 lock (m_uniqueReleasedMeshes)
1221 {
1222 try
1223 {
1224 m_uniqueReleasedMeshes.Add(unitKey, UnitMesh);
1225 }
1226 catch { }
1227 }
1228 }
1229
1230 mesh = UnitMesh.Scale(size);
1231 mesh.Key = key;
1232 mesh.RefCount = 1;
1233 lock (m_uniqueMeshes)
1234 {
1235 try
1236 {
1237 m_uniqueMeshes.Add(key, mesh);
1238 }
1239 catch { }
1240 }
1241
1242 return mesh;
1243 }
1244
1245 public void ReleaseMesh(IMesh imesh)
1246 {
1247 if (imesh == null)
1248 return;
1249
1250 Mesh mesh = (Mesh)imesh;
1251
1252 lock (m_uniqueMeshes)
1253 {
1254 int curRefCount = mesh.RefCount;
1255 curRefCount--;
1256
1257 if (curRefCount > 0)
1258 {
1259 mesh.RefCount = curRefCount;
1260 return;
1261 }
1262
1263 mesh.RefCount = 0;
1264 m_uniqueMeshes.Remove(mesh.Key);
1265 lock (m_uniqueReleasedMeshes)
1266 {
1267 try
1268 {
1269 m_uniqueReleasedMeshes.Add(mesh.Key, mesh);
1270 }
1271 catch { }
1272 }
1273 }
1274 }
1275
1276 public void ExpireReleaseMeshs()
1277 {
1278 if (m_uniqueReleasedMeshes.Count == 0)
1279 return;
1280
1281 List<Mesh> meshstodelete = new List<Mesh>();
1282 int refcntr;
1283
1284 lock (m_uniqueReleasedMeshes)
1285 {
1286 foreach (Mesh m in m_uniqueReleasedMeshes.Values)
1287 {
1288 refcntr = m.RefCount;
1289 refcntr--;
1290 if (refcntr > -6)
1291 m.RefCount = refcntr;
1292 else
1293 meshstodelete.Add(m);
1294 }
1295
1296 foreach (Mesh m in meshstodelete)
1297 {
1298 m_uniqueReleasedMeshes.Remove(m.Key);
1299 m.releaseBuildingMeshData();
1300 m.releasePinned();
1301 }
1302 }
1303 }
1304
1305 public void FileNames(AMeshKey key, out string dir,out string fullFileName)
1306 {
1307 string id = key.ToString();
1308 string init = id.Substring(0, 1);
1309 dir = System.IO.Path.Combine(cachePath, init);
1310 fullFileName = System.IO.Path.Combine(dir, id);
1311 }
1312
1313 public string FullFileName(AMeshKey key)
1314 {
1315 string id = key.ToString();
1316 string init = id.Substring(0,1);
1317 id = System.IO.Path.Combine(init, id);
1318 id = System.IO.Path.Combine(cachePath, id);
1319 return id;
1320 }
1321
1322 private Mesh GetFromFileCache(AMeshKey key)
1323 {
1324 Mesh mesh = null;
1325 string filename = FullFileName(key);
1326 bool ok = true;
1327
1328 lock (diskLock)
1329 {
1330 if (File.Exists(filename))
1331 {
1332 FileStream stream = null;
1333 try
1334 {
1335 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
1336 BinaryFormatter bformatter = new BinaryFormatter();
1337
1338 mesh = Mesh.FromStream(stream, key);
1339
1340 }
1341 catch (Exception e)
1342 {
1343 ok = false;
1344 m_log.ErrorFormat(
1345 "[MESH CACHE]: Failed to get file {0}. Exception {1} {2}",
1346 filename, e.Message, e.StackTrace);
1347 }
1348
1349 if (stream != null)
1350 stream.Close();
1351
1352 if (mesh == null || !ok)
1353 File.Delete(filename);
1354 else
1355 File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
1356 }
1357 }
1358
1359 return mesh;
1360 }
1361
1362 private void StoreToFileCache(AMeshKey key, Mesh mesh)
1363 {
1364 Stream stream = null;
1365 bool ok = false;
1366
1367 // Make sure the target cache directory exists
1368 string dir = String.Empty;
1369 string filename = String.Empty;
1370
1371 FileNames(key, out dir, out filename);
1372
1373 lock (diskLock)
1374 {
1375 try
1376 {
1377 if (!Directory.Exists(dir))
1378 {
1379 Directory.CreateDirectory(dir);
1380 }
1381
1382 stream = File.Open(filename, FileMode.Create);
1383 ok = mesh.ToStream(stream);
1384 }
1385 catch (IOException e)
1386 {
1387 m_log.ErrorFormat(
1388 "[MESH CACHE]: Failed to write file {0}. Exception {1} {2}.",
1389 filename, e.Message, e.StackTrace);
1390 ok = false;
1391 }
1392
1393 if (stream != null)
1394 stream.Close();
1395
1396 if (File.Exists(filename))
1397 {
1398 if (ok)
1399 File.SetLastAccessTimeUtc(filename, DateTime.UtcNow);
1400 else
1401 File.Delete(filename);
1402 }
1403 }
1404 }
1405
1406 public void ExpireFileCache()
1407 {
1408 if (!doCacheExpire)
1409 return;
1410
1411 string controlfile = System.IO.Path.Combine(cachePath, "cntr");
1412
1413 lock (diskLock)
1414 {
1415 try
1416 {
1417 if (File.Exists(controlfile))
1418 {
1419 int ndeleted = 0;
1420 int totalfiles = 0;
1421 int ndirs = 0;
1422 DateTime OlderTime = File.GetLastAccessTimeUtc(controlfile) - CacheExpire;
1423 File.SetLastAccessTimeUtc(controlfile, DateTime.UtcNow);
1424
1425 foreach (string dir in Directory.GetDirectories(cachePath))
1426 {
1427 try
1428 {
1429 foreach (string file in Directory.GetFiles(dir))
1430 {
1431 try
1432 {
1433 if (File.GetLastAccessTimeUtc(file) < OlderTime)
1434 {
1435 File.Delete(file);
1436 ndeleted++;
1437 }
1438 }
1439 catch { }
1440 totalfiles++;
1441 }
1442 }
1443 catch { }
1444 ndirs++;
1445 }
1446
1447 if (ndeleted == 0)
1448 m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, no expires",
1449 totalfiles,ndirs);
1450 else
1451 m_log.InfoFormat("[MESH CACHE]: {0} Files in {1} cache folders, expired {2} files accessed before {3}",
1452 totalfiles,ndirs, ndeleted, OlderTime.ToString());
1453 }
1454 else
1455 {
1456 m_log.Info("[MESH CACHE]: Expire delayed to next startup");
1457 FileStream fs = File.Create(controlfile,4096,FileOptions.WriteThrough);
1458 fs.Close();
1459 }
1460 }
1461 catch { }
1462 }
1463 }
1464 }
1465}
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs
new file mode 100644
index 0000000..8eb136b
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs
@@ -0,0 +1,1708 @@
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 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;
31using System.IO;
32
33namespace PrimMesher
34{
35 public struct Quat
36 {
37 /// <summary>X value</summary>
38 public float X;
39 /// <summary>Y value</summary>
40 public float Y;
41 /// <summary>Z value</summary>
42 public float Z;
43 /// <summary>W value</summary>
44 public float W;
45
46 public Quat(float x, float y, float z, float w)
47 {
48 X = x;
49 Y = y;
50 Z = z;
51 W = w;
52 }
53
54 public Quat(Coord axis, float angle)
55 {
56 axis = axis.Normalize();
57
58 angle *= 0.5f;
59 float c = (float)Math.Cos(angle);
60 float s = (float)Math.Sin(angle);
61
62 X = axis.X * s;
63 Y = axis.Y * s;
64 Z = axis.Z * s;
65 W = c;
66
67 Normalize();
68 }
69
70 public float Length()
71 {
72 return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
73 }
74
75 public Quat Normalize()
76 {
77 const float MAG_THRESHOLD = 0.0000001f;
78 float mag = Length();
79
80 // Catch very small rounding errors when normalizing
81 if (mag > MAG_THRESHOLD)
82 {
83 float oomag = 1f / mag;
84 X *= oomag;
85 Y *= oomag;
86 Z *= oomag;
87 W *= oomag;
88 }
89 else
90 {
91 X = 0f;
92 Y = 0f;
93 Z = 0f;
94 W = 1f;
95 }
96
97 return this;
98 }
99
100 public static Quat operator *(Quat q1, Quat q2)
101 {
102 float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y;
103 float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X;
104 float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W;
105 float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z;
106 return new Quat(x, y, z, w);
107 }
108
109 public override string ToString()
110 {
111 return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">";
112 }
113 }
114
115 public struct Coord
116 {
117 public float X;
118 public float Y;
119 public float Z;
120
121 public Coord(float x, float y, float z)
122 {
123 this.X = x;
124 this.Y = y;
125 this.Z = z;
126 }
127
128 public float Length()
129 {
130 return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z);
131 }
132
133 public Coord Invert()
134 {
135 this.X = -this.X;
136 this.Y = -this.Y;
137 this.Z = -this.Z;
138
139 return this;
140 }
141
142 public Coord Normalize()
143 {
144 const float MAG_THRESHOLD = 0.0000001f;
145 float mag = Length();
146
147 // Catch very small rounding errors when normalizing
148 if (mag > MAG_THRESHOLD)
149 {
150 float oomag = 1.0f / mag;
151 this.X *= oomag;
152 this.Y *= oomag;
153 this.Z *= oomag;
154 }
155 else
156 {
157 this.X = 0.0f;
158 this.Y = 0.0f;
159 this.Z = 0.0f;
160 }
161
162 return this;
163 }
164
165 public override string ToString()
166 {
167 return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString();
168 }
169
170 public static Coord Cross(Coord c1, Coord c2)
171 {
172 return new Coord(
173 c1.Y * c2.Z - c2.Y * c1.Z,
174 c1.Z * c2.X - c2.Z * c1.X,
175 c1.X * c2.Y - c2.X * c1.Y
176 );
177 }
178
179 public static Coord operator +(Coord v, Coord a)
180 {
181 return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z);
182 }
183
184 public static Coord operator *(Coord v, Coord m)
185 {
186 return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z);
187 }
188
189 public static Coord operator *(Coord v, Quat q)
190 {
191 // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/
192
193 Coord c2 = new Coord(0.0f, 0.0f, 0.0f);
194
195 c2.X = q.W * q.W * v.X +
196 2f * q.Y * q.W * v.Z -
197 2f * q.Z * q.W * v.Y +
198 q.X * q.X * v.X +
199 2f * q.Y * q.X * v.Y +
200 2f * q.Z * q.X * v.Z -
201 q.Z * q.Z * v.X -
202 q.Y * q.Y * v.X;
203
204 c2.Y =
205 2f * q.X * q.Y * v.X +
206 q.Y * q.Y * v.Y +
207 2f * q.Z * q.Y * v.Z +
208 2f * q.W * q.Z * v.X -
209 q.Z * q.Z * v.Y +
210 q.W * q.W * v.Y -
211 2f * q.X * q.W * v.Z -
212 q.X * q.X * v.Y;
213
214 c2.Z =
215 2f * q.X * q.Z * v.X +
216 2f * q.Y * q.Z * v.Y +
217 q.Z * q.Z * v.Z -
218 2f * q.W * q.Y * v.X -
219 q.Y * q.Y * v.Z +
220 2f * q.W * q.X * v.Y -
221 q.X * q.X * v.Z +
222 q.W * q.W * v.Z;
223
224 return c2;
225 }
226 }
227
228 public struct Face
229 {
230 public int primFace;
231
232 // vertices
233 public int v1;
234 public int v2;
235 public int v3;
236
237 public Face(int v1, int v2, int v3)
238 {
239 primFace = 0;
240
241 this.v1 = v1;
242 this.v2 = v2;
243 this.v3 = v3;
244
245 }
246
247 public Coord SurfaceNormal(List<Coord> coordList)
248 {
249 Coord c1 = coordList[this.v1];
250 Coord c2 = coordList[this.v2];
251 Coord c3 = coordList[this.v3];
252
253 Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
254 Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
255
256 return Coord.Cross(edge1, edge2).Normalize();
257 }
258 }
259
260 internal struct Angle
261 {
262 internal float angle;
263 internal float X;
264 internal float Y;
265
266 internal Angle(float angle, float x, float y)
267 {
268 this.angle = angle;
269 this.X = x;
270 this.Y = y;
271 }
272 }
273
274 internal class AngleList
275 {
276 private float iX, iY; // intersection point
277
278 private static Angle[] angles3 =
279 {
280 new Angle(0.0f, 1.0f, 0.0f),
281 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
282 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
283 new Angle(1.0f, 1.0f, 0.0f)
284 };
285
286 private static Angle[] angles4 =
287 {
288 new Angle(0.0f, 1.0f, 0.0f),
289 new Angle(0.25f, 0.0f, 1.0f),
290 new Angle(0.5f, -1.0f, 0.0f),
291 new Angle(0.75f, 0.0f, -1.0f),
292 new Angle(1.0f, 1.0f, 0.0f)
293 };
294
295 private static Angle[] angles6 =
296 {
297 new Angle(0.0f, 1.0f, 0.0f),
298 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
299 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
300 new Angle(0.5f, -1.0f, 0.0f),
301 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
302 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
303 new Angle(1.0f, 1.0f, 0.0f)
304 };
305
306 private static Angle[] angles12 =
307 {
308 new Angle(0.0f, 1.0f, 0.0f),
309 new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
310 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
311 new Angle(0.25f, 0.0f, 1.0f),
312 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
313 new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
314 new Angle(0.5f, -1.0f, 0.0f),
315 new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
316 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
317 new Angle(0.75f, 0.0f, -1.0f),
318 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
319 new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
320 new Angle(1.0f, 1.0f, 0.0f)
321 };
322
323 private static Angle[] angles24 =
324 {
325 new Angle(0.0f, 1.0f, 0.0f),
326 new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f),
327 new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
328 new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f),
329 new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
330 new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f),
331 new Angle(0.25f, 0.0f, 1.0f),
332 new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f),
333 new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
334 new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f),
335 new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f),
336 new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f),
337 new Angle(0.5f, -1.0f, 0.0f),
338 new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f),
339 new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f),
340 new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f),
341 new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f),
342 new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f),
343 new Angle(0.75f, 0.0f, -1.0f),
344 new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f),
345 new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f),
346 new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f),
347 new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f),
348 new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f),
349 new Angle(1.0f, 1.0f, 0.0f)
350 };
351
352 private Angle interpolatePoints(float newPoint, Angle p1, Angle p2)
353 {
354 float m = (newPoint - p1.angle) / (p2.angle - p1.angle);
355 return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y));
356 }
357
358 private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
359 { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
360 double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
361 double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
362
363 if (denom != 0.0)
364 {
365 double ua = uaNumerator / denom;
366 iX = (float)(x1 + ua * (x2 - x1));
367 iY = (float)(y1 + ua * (y2 - y1));
368 }
369 }
370
371 internal List<Angle> angles;
372
373 internal void makeAngles(int sides, float startAngle, float stopAngle, bool hasCut)
374 {
375 angles = new List<Angle>();
376
377 const double twoPi = System.Math.PI * 2.0;
378 const float twoPiInv = (float)(1.0d / twoPi);
379
380 if (sides < 1)
381 throw new Exception("number of sides not greater than zero");
382 if (stopAngle <= startAngle)
383 throw new Exception("stopAngle not greater than startAngle");
384
385 if ((sides == 3 || sides == 4 || sides == 6 || sides == 12 || sides == 24))
386 {
387 startAngle *= twoPiInv;
388 stopAngle *= twoPiInv;
389
390 Angle[] sourceAngles;
391 switch (sides)
392 {
393 case 3:
394 sourceAngles = angles3;
395 break;
396 case 4:
397 sourceAngles = angles4;
398 break;
399 case 6:
400 sourceAngles = angles6;
401 break;
402 case 12:
403 sourceAngles = angles12;
404 break;
405 default:
406 sourceAngles = angles24;
407 break;
408 }
409
410 int startAngleIndex = (int)(startAngle * sides);
411 int endAngleIndex = sourceAngles.Length - 1;
412
413 if (hasCut)
414 {
415 if (stopAngle < 1.0f)
416 endAngleIndex = (int)(stopAngle * sides) + 1;
417 if (endAngleIndex == startAngleIndex)
418 endAngleIndex++;
419
420 for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++)
421 {
422 angles.Add(sourceAngles[angleIndex]);
423 }
424
425 if (startAngle > 0.0f)
426 angles[0] = interpolatePoints(startAngle, angles[0], angles[1]);
427
428 if (stopAngle < 1.0f)
429 {
430 int lastAngleIndex = angles.Count - 1;
431 angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]);
432 }
433 }
434 else
435 {
436 for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex; angleIndex++)
437 angles.Add(sourceAngles[angleIndex]);
438 }
439 }
440 else
441 {
442 double stepSize = twoPi / sides;
443
444 int startStep = (int)(startAngle / stepSize);
445 double angle = stepSize * startStep;
446 int step = startStep;
447 double stopAngleTest = stopAngle;
448 if (stopAngle < twoPi)
449 {
450 stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1);
451 if (stopAngleTest < stopAngle)
452 stopAngleTest += stepSize;
453 if (stopAngleTest > twoPi)
454 stopAngleTest = twoPi;
455 }
456
457 while (angle <= stopAngleTest)
458 {
459 Angle newAngle;
460 newAngle.angle = (float)angle;
461 newAngle.X = (float)System.Math.Cos(angle);
462 newAngle.Y = (float)System.Math.Sin(angle);
463 angles.Add(newAngle);
464 step += 1;
465 angle = stepSize * step;
466 }
467
468 if (startAngle > angles[0].angle)
469 {
470 Angle newAngle;
471 intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle));
472 newAngle.angle = startAngle;
473 newAngle.X = iX;
474 newAngle.Y = iY;
475 angles[0] = newAngle;
476 }
477
478 int index = angles.Count - 1;
479 if (stopAngle < angles[index].angle)
480 {
481 Angle newAngle;
482 intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle));
483 newAngle.angle = stopAngle;
484 newAngle.X = iX;
485 newAngle.Y = iY;
486 angles[index] = newAngle;
487 }
488 }
489 }
490 }
491
492 /// <summary>
493 /// generates a profile for extrusion
494 /// </summary>
495 public class Profile
496 {
497 private const float twoPi = 2.0f * (float)Math.PI;
498
499 public string errorMessage = null;
500
501 public List<Coord> coords;
502 public List<Face> faces;
503
504 // use these for making individual meshes for each prim face
505 public List<int> outerCoordIndices = null;
506 public List<int> hollowCoordIndices = null;
507
508 public int numOuterVerts = 0;
509 public int numHollowVerts = 0;
510
511 public int outerFaceNumber = -1;
512 public int hollowFaceNumber = -1;
513
514 public int bottomFaceNumber = 0;
515 public int numPrimFaces = 0;
516
517 public Profile()
518 {
519 this.coords = new List<Coord>();
520 this.faces = new List<Face>();
521 }
522
523 public Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool hasProfileCut, bool createFaces)
524 {
525 const float halfSqr2 = 0.7071067811866f;
526
527 this.coords = new List<Coord>();
528 this.faces = new List<Face>();
529
530 List<Coord> hollowCoords = new List<Coord>();
531
532 bool hasHollow = (hollow > 0.0f);
533
534 AngleList angles = new AngleList();
535 AngleList hollowAngles = new AngleList();
536
537 float xScale = 0.5f;
538 float yScale = 0.5f;
539 if (sides == 4) // corners of a square are sqrt(2) from center
540 {
541 xScale = halfSqr2;
542 yScale = halfSqr2;
543 }
544
545 float startAngle = profileStart * twoPi;
546 float stopAngle = profileEnd * twoPi;
547
548 try { angles.makeAngles(sides, startAngle, stopAngle,hasProfileCut); }
549 catch (Exception ex)
550 {
551
552 errorMessage = "makeAngles failed: Exception: " + ex.ToString()
553 + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();
554
555 return;
556 }
557
558 this.numOuterVerts = angles.angles.Count;
559
560 Angle angle;
561 Coord newVert = new Coord();
562
563 // flag to create as few triangles as possible for 3 or 4 side profile
564 bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);
565
566 if (hasHollow)
567 {
568 if (sides == hollowSides)
569 hollowAngles = angles;
570 else
571 {
572 try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle, hasProfileCut); }
573 catch (Exception ex)
574 {
575 errorMessage = "makeAngles failed: Exception: " + ex.ToString()
576 + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString();
577
578 return;
579 }
580
581 int numHollowAngles = hollowAngles.angles.Count;
582 for (int i = 0; i < numHollowAngles; i++)
583 {
584 angle = hollowAngles.angles[i];
585 newVert.X = hollow * xScale * angle.X;
586 newVert.Y = hollow * yScale * angle.Y;
587 newVert.Z = 0.0f;
588
589 hollowCoords.Add(newVert);
590 }
591 }
592 this.numHollowVerts = hollowAngles.angles.Count;
593 }
594 else if (!simpleFace)
595 {
596 Coord center = new Coord(0.0f, 0.0f, 0.0f);
597 this.coords.Add(center);
598 }
599
600 int numAngles = angles.angles.Count;
601 bool hollowsame = (hasHollow && hollowSides == sides);
602
603 for (int i = 0; i < numAngles; i++)
604 {
605 angle = angles.angles[i];
606 newVert.X = angle.X * xScale;
607 newVert.Y = angle.Y * yScale;
608 newVert.Z = 0.0f;
609 this.coords.Add(newVert);
610 if (hollowsame)
611 {
612 newVert.X *= hollow;
613 newVert.Y *= hollow;
614 hollowCoords.Add(newVert);
615 }
616 }
617
618 if (hasHollow)
619 {
620 hollowCoords.Reverse();
621 this.coords.AddRange(hollowCoords);
622
623 if (createFaces)
624 {
625 int numTotalVerts = this.numOuterVerts + this.numHollowVerts;
626
627 if (this.numOuterVerts == this.numHollowVerts)
628 {
629 Face newFace = new Face();
630
631 for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++)
632 {
633 newFace.v1 = coordIndex;
634 newFace.v2 = coordIndex + 1;
635 newFace.v3 = numTotalVerts - coordIndex - 1;
636 this.faces.Add(newFace);
637
638 newFace.v1 = coordIndex + 1;
639 newFace.v2 = numTotalVerts - coordIndex - 2;
640 newFace.v3 = numTotalVerts - coordIndex - 1;
641 this.faces.Add(newFace);
642 }
643 if (!hasProfileCut)
644 {
645 newFace.v1 = this.numOuterVerts - 1;
646 newFace.v2 = 0;
647 newFace.v3 = this.numOuterVerts;
648 this.faces.Add(newFace);
649
650 newFace.v1 = 0;
651 newFace.v2 = numTotalVerts - 1;
652 newFace.v3 = this.numOuterVerts;
653 this.faces.Add(newFace);
654 }
655 }
656 else if (this.numOuterVerts < this.numHollowVerts)
657 {
658 Face newFace = new Face();
659 int j = 0; // j is the index for outer vertices
660 int i;
661 int maxJ = this.numOuterVerts - 1;
662 float curHollowAngle = 0;
663 for (i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices
664 {
665 curHollowAngle = hollowAngles.angles[i].angle;
666 if (j < maxJ)
667 {
668 if (angles.angles[j + 1].angle - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f)
669 {
670 newFace.v1 = numTotalVerts - i - 1;
671 newFace.v2 = j;
672 newFace.v3 = j + 1;
673 this.faces.Add(newFace);
674 j++;
675 }
676 }
677 else
678 {
679 if (1.0f - curHollowAngle < curHollowAngle - angles.angles[j].angle + 0.000001f)
680 break;
681 }
682
683 newFace.v1 = j;
684 newFace.v2 = numTotalVerts - i - 2;
685 newFace.v3 = numTotalVerts - i - 1;
686
687 this.faces.Add(newFace);
688 }
689
690 if (!hasProfileCut)
691 {
692 if (i == this.numHollowVerts)
693 {
694 newFace.v1 = numTotalVerts - this.numHollowVerts;
695 newFace.v2 = maxJ;
696 newFace.v3 = 0;
697
698 this.faces.Add(newFace);
699 }
700 else
701 {
702 if (1.0f - curHollowAngle < curHollowAngle - angles.angles[maxJ].angle + 0.000001f)
703 {
704 newFace.v1 = numTotalVerts - i - 1;
705 newFace.v2 = maxJ;
706 newFace.v3 = 0;
707
708 this.faces.Add(newFace);
709 }
710
711 for (; i < this.numHollowVerts - 1; i++)
712 {
713 newFace.v1 = 0;
714 newFace.v2 = numTotalVerts - i - 2;
715 newFace.v3 = numTotalVerts - i - 1;
716
717 this.faces.Add(newFace);
718 }
719 }
720
721 newFace.v1 = 0;
722 newFace.v2 = numTotalVerts - this.numHollowVerts;
723 newFace.v3 = numTotalVerts - 1;
724 this.faces.Add(newFace);
725 }
726 }
727 else // numHollowVerts < numOuterVerts
728 {
729 Face newFace = new Face();
730 int j = 0; // j is the index for inner vertices
731 int maxJ = this.numHollowVerts - 1;
732 for (int i = 0; i < this.numOuterVerts; i++)
733 {
734 if (j < maxJ)
735 if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f)
736 {
737 newFace.v1 = i;
738 newFace.v2 = numTotalVerts - j - 2;
739 newFace.v3 = numTotalVerts - j - 1;
740
741 this.faces.Add(newFace);
742 j += 1;
743 }
744
745 newFace.v1 = numTotalVerts - j - 1;
746 newFace.v2 = i;
747 newFace.v3 = i + 1;
748
749 this.faces.Add(newFace);
750 }
751
752 if (!hasProfileCut)
753 {
754 int i = this.numOuterVerts - 1;
755
756 if (hollowAngles.angles[0].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[maxJ].angle + 0.000001f)
757 {
758 newFace.v1 = 0;
759 newFace.v2 = numTotalVerts - maxJ - 1;
760 newFace.v3 = numTotalVerts - 1;
761
762 this.faces.Add(newFace);
763 }
764
765 newFace.v1 = numTotalVerts - maxJ - 1;
766 newFace.v2 = i;
767 newFace.v3 = 0;
768
769 this.faces.Add(newFace);
770 }
771 }
772 }
773
774 }
775
776 else if (createFaces)
777 {
778 if (simpleFace)
779 {
780 if (sides == 3)
781 this.faces.Add(new Face(0, 1, 2));
782 else if (sides == 4)
783 {
784 this.faces.Add(new Face(0, 1, 2));
785 this.faces.Add(new Face(0, 2, 3));
786 }
787 }
788 else
789 {
790 for (int i = 1; i < numAngles ; i++)
791 {
792 Face newFace = new Face();
793 newFace.v1 = 0;
794 newFace.v2 = i;
795 newFace.v3 = i + 1;
796 this.faces.Add(newFace);
797 }
798 if (!hasProfileCut)
799 {
800 Face newFace = new Face();
801 newFace.v1 = 0;
802 newFace.v2 = numAngles;
803 newFace.v3 = 1;
804 this.faces.Add(newFace);
805 }
806 }
807 }
808
809
810 hollowCoords = null;
811 }
812
813
814 public Profile Copy()
815 {
816 return this.Copy(true);
817 }
818
819 public Profile Copy(bool needFaces)
820 {
821 Profile copy = new Profile();
822
823 copy.coords.AddRange(this.coords);
824
825 if (needFaces)
826 copy.faces.AddRange(this.faces);
827
828 copy.numOuterVerts = this.numOuterVerts;
829 copy.numHollowVerts = this.numHollowVerts;
830
831 return copy;
832 }
833
834 public void AddPos(Coord v)
835 {
836 this.AddPos(v.X, v.Y, v.Z);
837 }
838
839 public void AddPos(float x, float y, float z)
840 {
841 int i;
842 int numVerts = this.coords.Count;
843 Coord vert;
844
845 for (i = 0; i < numVerts; i++)
846 {
847 vert = this.coords[i];
848 vert.X += x;
849 vert.Y += y;
850 vert.Z += z;
851 this.coords[i] = vert;
852 }
853 }
854
855 public void AddRot(Quat q)
856 {
857 int i;
858 int numVerts = this.coords.Count;
859
860 for (i = 0; i < numVerts; i++)
861 this.coords[i] *= q;
862 }
863
864 public void Scale(float x, float y)
865 {
866 int i;
867 int numVerts = this.coords.Count;
868 Coord vert;
869
870 for (i = 0; i < numVerts; i++)
871 {
872 vert = this.coords[i];
873 vert.X *= x;
874 vert.Y *= y;
875 this.coords[i] = vert;
876 }
877 }
878
879 /// <summary>
880 /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices
881 /// </summary>
882 public void FlipNormals()
883 {
884 int i;
885 int numFaces = this.faces.Count;
886 Face tmpFace;
887 int tmp;
888
889 for (i = 0; i < numFaces; i++)
890 {
891 tmpFace = this.faces[i];
892 tmp = tmpFace.v3;
893 tmpFace.v3 = tmpFace.v1;
894 tmpFace.v1 = tmp;
895 this.faces[i] = tmpFace;
896 }
897 }
898
899 public void AddValue2FaceVertexIndices(int num)
900 {
901 int numFaces = this.faces.Count;
902 Face tmpFace;
903 for (int i = 0; i < numFaces; i++)
904 {
905 tmpFace = this.faces[i];
906 tmpFace.v1 += num;
907 tmpFace.v2 += num;
908 tmpFace.v3 += num;
909
910 this.faces[i] = tmpFace;
911 }
912 }
913
914 public void DumpRaw(String path, String name, String title)
915 {
916 if (path == null)
917 return;
918 String fileName = name + "_" + title + ".raw";
919 String completePath = System.IO.Path.Combine(path, fileName);
920 StreamWriter sw = new StreamWriter(completePath);
921
922 for (int i = 0; i < this.faces.Count; i++)
923 {
924 string s = this.coords[this.faces[i].v1].ToString();
925 s += " " + this.coords[this.faces[i].v2].ToString();
926 s += " " + this.coords[this.faces[i].v3].ToString();
927
928 sw.WriteLine(s);
929 }
930
931 sw.Close();
932 }
933 }
934
935 public struct PathNode
936 {
937 public Coord position;
938 public Quat rotation;
939 public float xScale;
940 public float yScale;
941 public float percentOfPath;
942 }
943
944 public enum PathType { Linear = 0, Circular = 1, Flexible = 2 }
945
946 public class Path
947 {
948 public List<PathNode> pathNodes = new List<PathNode>();
949
950 public float twistBegin = 0.0f;
951 public float twistEnd = 0.0f;
952 public float topShearX = 0.0f;
953 public float topShearY = 0.0f;
954 public float pathCutBegin = 0.0f;
955 public float pathCutEnd = 1.0f;
956 public float dimpleBegin = 0.0f;
957 public float dimpleEnd = 1.0f;
958 public float skew = 0.0f;
959 public float holeSizeX = 1.0f; // called pathScaleX in pbs
960 public float holeSizeY = 0.25f;
961 public float taperX = 0.0f;
962 public float taperY = 0.0f;
963 public float radius = 0.0f;
964 public float revolutions = 1.0f;
965 public int stepsPerRevolution = 24;
966
967 private const float twoPi = 2.0f * (float)Math.PI;
968
969 public void Create(PathType pathType, int steps)
970 {
971 if (this.taperX > 0.999f)
972 this.taperX = 0.999f;
973 if (this.taperX < -0.999f)
974 this.taperX = -0.999f;
975 if (this.taperY > 0.999f)
976 this.taperY = 0.999f;
977 if (this.taperY < -0.999f)
978 this.taperY = -0.999f;
979
980 if (pathType == PathType.Linear || pathType == PathType.Flexible)
981 {
982 int step = 0;
983
984 float length = this.pathCutEnd - this.pathCutBegin;
985 float twistTotal = twistEnd - twistBegin;
986 float twistTotalAbs = Math.Abs(twistTotal);
987 if (twistTotalAbs > 0.01f)
988 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
989
990 float start = -0.5f;
991 float stepSize = length / (float)steps;
992 float percentOfPathMultiplier = stepSize * 0.999999f;
993 float xOffset = this.topShearX * this.pathCutBegin;
994 float yOffset = this.topShearY * this.pathCutBegin;
995 float zOffset = start;
996 float xOffsetStepIncrement = this.topShearX * length / steps;
997 float yOffsetStepIncrement = this.topShearY * length / steps;
998
999 float percentOfPath = this.pathCutBegin;
1000 zOffset += percentOfPath;
1001
1002 // sanity checks
1003
1004 bool done = false;
1005
1006 while (!done)
1007 {
1008 PathNode newNode = new PathNode();
1009
1010 newNode.xScale = 1.0f;
1011 if (this.taperX == 0.0f)
1012 newNode.xScale = 1.0f;
1013 else if (this.taperX > 0.0f)
1014 newNode.xScale = 1.0f - percentOfPath * this.taperX;
1015 else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX;
1016
1017 newNode.yScale = 1.0f;
1018 if (this.taperY == 0.0f)
1019 newNode.yScale = 1.0f;
1020 else if (this.taperY > 0.0f)
1021 newNode.yScale = 1.0f - percentOfPath * this.taperY;
1022 else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY;
1023
1024 float twist = twistBegin + twistTotal * percentOfPath;
1025
1026 newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
1027 newNode.position = new Coord(xOffset, yOffset, zOffset);
1028 newNode.percentOfPath = percentOfPath;
1029
1030 pathNodes.Add(newNode);
1031
1032 if (step < steps)
1033 {
1034 step += 1;
1035 percentOfPath += percentOfPathMultiplier;
1036 xOffset += xOffsetStepIncrement;
1037 yOffset += yOffsetStepIncrement;
1038 zOffset += stepSize;
1039 if (percentOfPath > this.pathCutEnd)
1040 done = true;
1041 }
1042 else done = true;
1043 }
1044 } // end of linear path code
1045
1046 else // pathType == Circular
1047 {
1048 float twistTotal = twistEnd - twistBegin;
1049
1050 // if the profile has a lot of twist, add more layers otherwise the layers may overlap
1051 // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't
1052 // accurately match the viewer
1053 float twistTotalAbs = Math.Abs(twistTotal);
1054 if (twistTotalAbs > 0.01f)
1055 {
1056 if (twistTotalAbs > Math.PI * 1.5f)
1057 steps *= 2;
1058 if (twistTotalAbs > Math.PI * 3.0f)
1059 steps *= 2;
1060 }
1061
1062 float yPathScale = this.holeSizeY * 0.5f;
1063 float pathLength = this.pathCutEnd - this.pathCutBegin;
1064 float totalSkew = this.skew * 2.0f * pathLength;
1065 float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew;
1066 float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY));
1067 float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f;
1068
1069 // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end
1070 // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used
1071 // to calculate the sine for generating the path radius appears to approximate it's effects there
1072 // too, but there are some subtle differences in the radius which are noticeable as the prim size
1073 // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on
1074 // the meshes generated with this technique appear nearly identical in shape to the same prims when
1075 // displayed by the viewer.
1076
1077 float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f;
1078 float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f;
1079 float stepSize = twoPi / this.stepsPerRevolution;
1080
1081 int step = (int)(startAngle / stepSize);
1082 float angle = startAngle;
1083
1084 bool done = false;
1085 while (!done) // loop through the length of the path and add the layers
1086 {
1087 PathNode newNode = new PathNode();
1088
1089 float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX;
1090 float yProfileScale = this.holeSizeY;
1091
1092 float percentOfPath = angle / (twoPi * this.revolutions);
1093 float percentOfAngles = (angle - startAngle) / (endAngle - startAngle);
1094
1095 if (this.taperX > 0.01f)
1096 xProfileScale *= 1.0f - percentOfPath * this.taperX;
1097 else if (this.taperX < -0.01f)
1098 xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX;
1099
1100 if (this.taperY > 0.01f)
1101 yProfileScale *= 1.0f - percentOfPath * this.taperY;
1102 else if (this.taperY < -0.01f)
1103 yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY;
1104
1105 newNode.xScale = xProfileScale;
1106 newNode.yScale = yProfileScale;
1107
1108 float radiusScale = 1.0f;
1109 if (this.radius > 0.001f)
1110 radiusScale = 1.0f - this.radius * percentOfPath;
1111 else if (this.radius < 0.001f)
1112 radiusScale = 1.0f + this.radius * (1.0f - percentOfPath);
1113
1114 float twist = twistBegin + twistTotal * percentOfPath;
1115
1116 float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
1117 xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
1118
1119 float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
1120
1121 float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale;
1122
1123 newNode.position = new Coord(xOffset, yOffset, zOffset);
1124
1125 // now orient the rotation of the profile layer relative to it's position on the path
1126 // adding taperY to the angle used to generate the quat appears to approximate the viewer
1127
1128 newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY);
1129
1130 // next apply twist rotation to the profile layer
1131 if (twistTotal != 0.0f || twistBegin != 0.0f)
1132 newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist);
1133
1134 newNode.percentOfPath = percentOfPath;
1135
1136 pathNodes.Add(newNode);
1137
1138 // calculate terms for next iteration
1139 // calculate the angle for the next iteration of the loop
1140
1141 if (angle >= endAngle - 0.01)
1142 done = true;
1143 else
1144 {
1145 step += 1;
1146 angle = stepSize * step;
1147 if (angle > endAngle)
1148 angle = endAngle;
1149 }
1150 }
1151 }
1152 }
1153 }
1154
1155 public class PrimMesh
1156 {
1157 public string errorMessage = "";
1158 private const float twoPi = 2.0f * (float)Math.PI;
1159
1160 public List<Coord> coords;
1161// public List<Coord> normals;
1162 public List<Face> faces;
1163
1164 private int sides = 4;
1165 private int hollowSides = 4;
1166 private float profileStart = 0.0f;
1167 private float profileEnd = 1.0f;
1168 private float hollow = 0.0f;
1169 public int twistBegin = 0;
1170 public int twistEnd = 0;
1171 public float topShearX = 0.0f;
1172 public float topShearY = 0.0f;
1173 public float pathCutBegin = 0.0f;
1174 public float pathCutEnd = 1.0f;
1175 public float dimpleBegin = 0.0f;
1176 public float dimpleEnd = 1.0f;
1177 public float skew = 0.0f;
1178 public float holeSizeX = 1.0f; // called pathScaleX in pbs
1179 public float holeSizeY = 0.25f;
1180 public float taperX = 0.0f;
1181 public float taperY = 0.0f;
1182 public float radius = 0.0f;
1183 public float revolutions = 1.0f;
1184 public int stepsPerRevolution = 24;
1185
1186 private bool hasProfileCut = false;
1187 private bool hasHollow = false;
1188
1189 public int numPrimFaces = 0;
1190
1191 /// <summary>
1192 /// Human readable string representation of the parameters used to create a mesh.
1193 /// </summary>
1194 /// <returns></returns>
1195 public string ParamsToDisplayString()
1196 {
1197 string s = "";
1198 s += "sides..................: " + this.sides.ToString();
1199 s += "\nhollowSides..........: " + this.hollowSides.ToString();
1200 s += "\nprofileStart.........: " + this.profileStart.ToString();
1201 s += "\nprofileEnd...........: " + this.profileEnd.ToString();
1202 s += "\nhollow...............: " + this.hollow.ToString();
1203 s += "\ntwistBegin...........: " + this.twistBegin.ToString();
1204 s += "\ntwistEnd.............: " + this.twistEnd.ToString();
1205 s += "\ntopShearX............: " + this.topShearX.ToString();
1206 s += "\ntopShearY............: " + this.topShearY.ToString();
1207 s += "\npathCutBegin.........: " + this.pathCutBegin.ToString();
1208 s += "\npathCutEnd...........: " + this.pathCutEnd.ToString();
1209 s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString();
1210 s += "\ndimpleEnd............: " + this.dimpleEnd.ToString();
1211 s += "\nskew.................: " + this.skew.ToString();
1212 s += "\nholeSizeX............: " + this.holeSizeX.ToString();
1213 s += "\nholeSizeY............: " + this.holeSizeY.ToString();
1214 s += "\ntaperX...............: " + this.taperX.ToString();
1215 s += "\ntaperY...............: " + this.taperY.ToString();
1216 s += "\nradius...............: " + this.radius.ToString();
1217 s += "\nrevolutions..........: " + this.revolutions.ToString();
1218 s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString();
1219 s += "\nhasProfileCut........: " + this.hasProfileCut.ToString();
1220 s += "\nhasHollow............: " + this.hasHollow.ToString();
1221
1222 return s;
1223 }
1224
1225 public bool HasProfileCut
1226 {
1227 get { return hasProfileCut; }
1228 set { hasProfileCut = value; }
1229 }
1230
1231 public bool HasHollow
1232 {
1233 get { return hasHollow; }
1234 }
1235
1236
1237 /// <summary>
1238 /// Constructs a PrimMesh object and creates the profile for extrusion.
1239 /// </summary>
1240 /// <param name="sides"></param>
1241 /// <param name="profileStart"></param>
1242 /// <param name="profileEnd"></param>
1243 /// <param name="hollow"></param>
1244 /// <param name="hollowSides"></param>
1245 /// <param name="sphereMode"></param>
1246 public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides)
1247 {
1248 this.coords = new List<Coord>();
1249 this.faces = new List<Face>();
1250
1251 this.sides = sides;
1252 this.profileStart = profileStart;
1253 this.profileEnd = profileEnd;
1254 this.hollow = hollow;
1255 this.hollowSides = hollowSides;
1256
1257 if (sides < 3)
1258 this.sides = 3;
1259 if (hollowSides < 3)
1260 this.hollowSides = 3;
1261 if (profileStart < 0.0f)
1262 this.profileStart = 0.0f;
1263 if (profileEnd > 1.0f)
1264 this.profileEnd = 1.0f;
1265 if (profileEnd < 0.02f)
1266 this.profileEnd = 0.02f;
1267 if (profileStart >= profileEnd)
1268 this.profileStart = profileEnd - 0.02f;
1269 if (hollow > 0.99f)
1270 this.hollow = 0.99f;
1271 if (hollow < 0.0f)
1272 this.hollow = 0.0f;
1273 }
1274
1275 /// <summary>
1276 /// Extrudes a profile along a path.
1277 /// </summary>
1278 public void Extrude(PathType pathType)
1279 {
1280 bool needEndFaces = false;
1281
1282 this.coords = new List<Coord>();
1283 this.faces = new List<Face>();
1284
1285 int steps = 1;
1286
1287 float length = this.pathCutEnd - this.pathCutBegin;
1288
1289 this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f;
1290
1291 this.hasHollow = (this.hollow > 0.001f);
1292
1293 float twistBegin = this.twistBegin / 360.0f * twoPi;
1294 float twistEnd = this.twistEnd / 360.0f * twoPi;
1295 float twistTotal = twistEnd - twistBegin;
1296 float twistTotalAbs = Math.Abs(twistTotal);
1297 if (twistTotalAbs > 0.01f)
1298 steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number
1299
1300 float hollow = this.hollow;
1301
1302 if (pathType == PathType.Circular)
1303 {
1304 needEndFaces = false;
1305 if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f)
1306 needEndFaces = true;
1307 else if (this.taperX != 0.0f || this.taperY != 0.0f)
1308 needEndFaces = true;
1309 else if (this.skew != 0.0f)
1310 needEndFaces = true;
1311 else if (twistTotal != 0.0f)
1312 needEndFaces = true;
1313 else if (this.radius != 0.0f)
1314 needEndFaces = true;
1315 }
1316 else needEndFaces = true;
1317
1318 // sanity checks
1319 float initialProfileRot = 0.0f;
1320 if (pathType == PathType.Circular)
1321 {
1322 if (this.sides == 3)
1323 {
1324 initialProfileRot = (float)Math.PI;
1325 if (this.hollowSides == 4)
1326 {
1327 if (hollow > 0.7f)
1328 hollow = 0.7f;
1329 hollow *= 0.707f;
1330 }
1331 else hollow *= 0.5f;
1332 }
1333 else if (this.sides == 4)
1334 {
1335 initialProfileRot = 0.25f * (float)Math.PI;
1336 if (this.hollowSides != 4)
1337 hollow *= 0.707f;
1338 }
1339 else if (this.sides > 4)
1340 {
1341 initialProfileRot = (float)Math.PI;
1342 if (this.hollowSides == 4)
1343 {
1344 if (hollow > 0.7f)
1345 hollow = 0.7f;
1346 hollow /= 0.7f;
1347 }
1348 }
1349 }
1350 else
1351 {
1352 if (this.sides == 3)
1353 {
1354 if (this.hollowSides == 4)
1355 {
1356 if (hollow > 0.7f)
1357 hollow = 0.7f;
1358 hollow *= 0.707f;
1359 }
1360 else hollow *= 0.5f;
1361 }
1362 else if (this.sides == 4)
1363 {
1364 initialProfileRot = 1.25f * (float)Math.PI;
1365 if (this.hollowSides != 4)
1366 hollow *= 0.707f;
1367 }
1368 else if (this.sides == 24 && this.hollowSides == 4)
1369 hollow *= 1.414f;
1370 }
1371
1372 Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, this.hasProfileCut,true);
1373 this.errorMessage = profile.errorMessage;
1374
1375 this.numPrimFaces = profile.numPrimFaces;
1376
1377 if (initialProfileRot != 0.0f)
1378 {
1379 profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot));
1380 }
1381
1382 float thisV = 0.0f;
1383 float lastV = 0.0f;
1384
1385 Path path = new Path();
1386 path.twistBegin = twistBegin;
1387 path.twistEnd = twistEnd;
1388 path.topShearX = topShearX;
1389 path.topShearY = topShearY;
1390 path.pathCutBegin = pathCutBegin;
1391 path.pathCutEnd = pathCutEnd;
1392 path.dimpleBegin = dimpleBegin;
1393 path.dimpleEnd = dimpleEnd;
1394 path.skew = skew;
1395 path.holeSizeX = holeSizeX;
1396 path.holeSizeY = holeSizeY;
1397 path.taperX = taperX;
1398 path.taperY = taperY;
1399 path.radius = radius;
1400 path.revolutions = revolutions;
1401 path.stepsPerRevolution = stepsPerRevolution;
1402
1403 path.Create(pathType, steps);
1404
1405 int lastNode = path.pathNodes.Count -1;
1406
1407 for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1408 {
1409 PathNode node = path.pathNodes[nodeIndex];
1410 Profile newLayer = profile.Copy();
1411
1412 newLayer.Scale(node.xScale, node.yScale);
1413 newLayer.AddRot(node.rotation);
1414 newLayer.AddPos(node.position);
1415
1416 if (needEndFaces && nodeIndex == 0)
1417 {
1418 newLayer.FlipNormals();
1419 } // if (nodeIndex == 0)
1420
1421 // append this layer
1422
1423 int coordsLen = this.coords.Count;
1424 newLayer.AddValue2FaceVertexIndices(coordsLen);
1425
1426 this.coords.AddRange(newLayer.coords);
1427
1428 if (needEndFaces)
1429 {
1430 if (nodeIndex == 0)
1431 this.faces.AddRange(newLayer.faces);
1432 else if (nodeIndex == lastNode)
1433 {
1434 if (node.xScale > 1e-6 && node.yScale > 1e-6)
1435 this.faces.AddRange(newLayer.faces);
1436 }
1437 }
1438
1439 // fill faces between layers
1440
1441 int numVerts = newLayer.coords.Count;
1442 Face newFace1 = new Face();
1443 Face newFace2 = new Face();
1444
1445 thisV = 1.0f - node.percentOfPath;
1446
1447 if (nodeIndex > 0)
1448 {
1449 int startVert = coordsLen;
1450 int endVert = this.coords.Count;
1451 if (!this.hasProfileCut)
1452 {
1453 int i = startVert;
1454 for (int l = 0; l < profile.numOuterVerts - 1; l++)
1455 {
1456 newFace1.v1 = i;
1457 newFace1.v2 = i - numVerts;
1458 newFace1.v3 = i + 1;
1459 this.faces.Add(newFace1);
1460
1461 newFace2.v1 = i + 1;
1462 newFace2.v2 = i - numVerts;
1463 newFace2.v3 = i + 1 - numVerts;
1464 this.faces.Add(newFace2);
1465 i++;
1466 }
1467
1468 newFace1.v1 = i;
1469 newFace1.v2 = i - numVerts;
1470 newFace1.v3 = startVert;
1471 this.faces.Add(newFace1);
1472
1473 newFace2.v1 = startVert;
1474 newFace2.v2 = i - numVerts;
1475 newFace2.v3 = startVert - numVerts;
1476 this.faces.Add(newFace2);
1477
1478 if (this.hasHollow)
1479 {
1480 startVert = ++i;
1481 for (int l = 0; l < profile.numHollowVerts - 1; l++)
1482 {
1483 newFace1.v1 = i;
1484 newFace1.v2 = i - numVerts;
1485 newFace1.v3 = i + 1;
1486 this.faces.Add(newFace1);
1487
1488 newFace2.v1 = i + 1;
1489 newFace2.v2 = i - numVerts;
1490 newFace2.v3 = i + 1 - numVerts;
1491 this.faces.Add(newFace2);
1492 i++;
1493 }
1494
1495 newFace1.v1 = i;
1496 newFace1.v2 = i - numVerts;
1497 newFace1.v3 = startVert;
1498 this.faces.Add(newFace1);
1499
1500 newFace2.v1 = startVert;
1501 newFace2.v2 = i - numVerts;
1502 newFace2.v3 = startVert - numVerts;
1503 this.faces.Add(newFace2);
1504 }
1505
1506
1507 }
1508 else
1509 {
1510 for (int i = startVert; i < endVert; i++)
1511 {
1512 int iNext = i + 1;
1513 if (i == endVert - 1)
1514 iNext = startVert;
1515
1516 newFace1.v1 = i;
1517 newFace1.v2 = i - numVerts;
1518 newFace1.v3 = iNext;
1519 this.faces.Add(newFace1);
1520
1521 newFace2.v1 = iNext;
1522 newFace2.v2 = i - numVerts;
1523 newFace2.v3 = iNext - numVerts;
1524 this.faces.Add(newFace2);
1525
1526 }
1527 }
1528 }
1529
1530 lastV = thisV;
1531
1532 } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++)
1533
1534 }
1535
1536
1537 /// <summary>
1538 /// DEPRICATED - use Extrude(PathType.Linear) instead
1539 /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism.
1540 /// </summary>
1541 ///
1542 public void ExtrudeLinear()
1543 {
1544 this.Extrude(PathType.Linear);
1545 }
1546
1547
1548 /// <summary>
1549 /// DEPRICATED - use Extrude(PathType.Circular) instead
1550 /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring.
1551 /// </summary>
1552 ///
1553 public void ExtrudeCircular()
1554 {
1555 this.Extrude(PathType.Circular);
1556 }
1557
1558
1559 private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3)
1560 {
1561 Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
1562 Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
1563
1564 Coord normal = Coord.Cross(edge1, edge2);
1565
1566 normal.Normalize();
1567
1568 return normal;
1569 }
1570
1571 private Coord SurfaceNormal(Face face)
1572 {
1573 return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]);
1574 }
1575
1576 /// <summary>
1577 /// Calculate the surface normal for a face in the list of faces
1578 /// </summary>
1579 /// <param name="faceIndex"></param>
1580 /// <returns></returns>
1581 public Coord SurfaceNormal(int faceIndex)
1582 {
1583 int numFaces = this.faces.Count;
1584 if (faceIndex < 0 || faceIndex >= numFaces)
1585 throw new Exception("faceIndex out of range");
1586
1587 return SurfaceNormal(this.faces[faceIndex]);
1588 }
1589
1590 /// <summary>
1591 /// Duplicates a PrimMesh object. All object properties are copied by value, including lists.
1592 /// </summary>
1593 /// <returns></returns>
1594 public PrimMesh Copy()
1595 {
1596 PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides);
1597 copy.twistBegin = this.twistBegin;
1598 copy.twistEnd = this.twistEnd;
1599 copy.topShearX = this.topShearX;
1600 copy.topShearY = this.topShearY;
1601 copy.pathCutBegin = this.pathCutBegin;
1602 copy.pathCutEnd = this.pathCutEnd;
1603 copy.dimpleBegin = this.dimpleBegin;
1604 copy.dimpleEnd = this.dimpleEnd;
1605 copy.skew = this.skew;
1606 copy.holeSizeX = this.holeSizeX;
1607 copy.holeSizeY = this.holeSizeY;
1608 copy.taperX = this.taperX;
1609 copy.taperY = this.taperY;
1610 copy.radius = this.radius;
1611 copy.revolutions = this.revolutions;
1612 copy.stepsPerRevolution = this.stepsPerRevolution;
1613
1614 copy.numPrimFaces = this.numPrimFaces;
1615 copy.errorMessage = this.errorMessage;
1616
1617 copy.coords = new List<Coord>(this.coords);
1618 copy.faces = new List<Face>(this.faces);
1619
1620 return copy;
1621 }
1622
1623 /// <summary>
1624 /// Adds a value to each XYZ vertex coordinate in the mesh
1625 /// </summary>
1626 /// <param name="x"></param>
1627 /// <param name="y"></param>
1628 /// <param name="z"></param>
1629 public void AddPos(float x, float y, float z)
1630 {
1631 int i;
1632 int numVerts = this.coords.Count;
1633 Coord vert;
1634
1635 for (i = 0; i < numVerts; i++)
1636 {
1637 vert = this.coords[i];
1638 vert.X += x;
1639 vert.Y += y;
1640 vert.Z += z;
1641 this.coords[i] = vert;
1642 }
1643 }
1644
1645 /// <summary>
1646 /// Rotates the mesh
1647 /// </summary>
1648 /// <param name="q"></param>
1649 public void AddRot(Quat q)
1650 {
1651 int i;
1652 int numVerts = this.coords.Count;
1653
1654 for (i = 0; i < numVerts; i++)
1655 this.coords[i] *= q;
1656 }
1657
1658#if VERTEX_INDEXER
1659 public VertexIndexer GetVertexIndexer()
1660 {
1661 return null;
1662 }
1663#endif
1664
1665 /// <summary>
1666 /// Scales the mesh
1667 /// </summary>
1668 /// <param name="x"></param>
1669 /// <param name="y"></param>
1670 /// <param name="z"></param>
1671 public void Scale(float x, float y, float z)
1672 {
1673 int i;
1674 int numVerts = this.coords.Count;
1675 //Coord vert;
1676
1677 Coord m = new Coord(x, y, z);
1678 for (i = 0; i < numVerts; i++)
1679 this.coords[i] *= m;
1680 }
1681
1682 /// <summary>
1683 /// Dumps the mesh to a Blender compatible "Raw" format file
1684 /// </summary>
1685 /// <param name="path"></param>
1686 /// <param name="name"></param>
1687 /// <param name="title"></param>
1688 public void DumpRaw(String path, String name, String title)
1689 {
1690 if (path == null)
1691 return;
1692 String fileName = name + "_" + title + ".raw";
1693 String completePath = System.IO.Path.Combine(path, fileName);
1694 StreamWriter sw = new StreamWriter(completePath);
1695
1696 for (int i = 0; i < this.faces.Count; i++)
1697 {
1698 string s = this.coords[this.faces[i].v1].ToString();
1699 s += " " + this.coords[this.faces[i].v2].ToString();
1700 s += " " + this.coords[this.faces[i].v3].ToString();
1701
1702 sw.WriteLine(s);
1703 }
1704
1705 sw.Close();
1706 }
1707 }
1708}
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Properties/AssemblyInfo.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..91df7ab
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4using Mono.Addins;
5
6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Region.PhysicsModule.ubODEMeshing")]
10[assembly: AssemblyDescription("Mesher for ubODE")]
11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("http://opensimulator.org")]
13[assembly: AssemblyProduct("OpenSim")]
14[assembly: AssemblyCopyright("OpenSimulator developers")]
15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")]
17
18// Setting ComVisible to false makes the types in this assembly not visible
19// to COM components. If you need to access a type in this assembly from
20// COM, set the ComVisible attribute to true on that type.
21[assembly: ComVisible(false)]
22
23// The following GUID is for the ID of the typelib if this project is exposed to COM
24[assembly: Guid("4b7e35c2-a9dd-4b10-b778-eb417f4f6884")]
25
26// Version information for an assembly consists of the following four values:
27//
28// Major Version
29// Minor Version
30// Build Number
31// Revision
32//
33[assembly: AssemblyVersion("0.8.2.*")]
34
35[assembly: Addin("OpenSim.Region.PhysicsModule.ubOdeMeshing", OpenSim.VersionInfo.VersionNumber)]
36[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMap.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMap.cs
new file mode 100644
index 0000000..1c75db6
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMap.cs
@@ -0,0 +1,244 @@
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 OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31
32using System.Drawing;
33using System.Drawing.Imaging;
34
35namespace PrimMesher
36{
37 public class SculptMap
38 {
39 public int width;
40 public int height;
41 public byte[] redBytes;
42 public byte[] greenBytes;
43 public byte[] blueBytes;
44
45 public SculptMap()
46 {
47 }
48
49 public SculptMap(Bitmap bm, int lod)
50 {
51 int bmW = bm.Width;
52 int bmH = bm.Height;
53
54 if (bmW == 0 || bmH == 0)
55 throw new Exception("SculptMap: bitmap has no data");
56
57 int numLodPixels = lod * lod; // (32 * 2)^2 = 64^2 pixels for default sculpt map image
58
59 bool needsScaling = false;
60 bool smallMap = false;
61
62 width = bmW;
63 height = bmH;
64
65 while (width * height > numLodPixels * 4)
66 {
67 width >>= 1;
68 height >>= 1;
69 needsScaling = true;
70 }
71
72 try
73 {
74 if (needsScaling)
75 bm = ScaleImage(bm, width, height);
76 }
77
78 catch (Exception e)
79 {
80 throw new Exception("Exception in ScaleImage(): e: " + e.ToString());
81 }
82
83 if (width * height > numLodPixels)
84 {
85 smallMap = false;
86 width >>= 1;
87 height >>= 1;
88 }
89 else
90 smallMap = true;
91
92 int numBytes = (width + 1) * (height + 1);
93 redBytes = new byte[numBytes];
94 greenBytes = new byte[numBytes];
95 blueBytes = new byte[numBytes];
96
97 int byteNdx = 0;
98 Color c;
99
100 try
101 {
102 for (int y = 0; y <= height; y++)
103 {
104 for (int x = 0; x < width; x++)
105 {
106 if (smallMap)
107 c = bm.GetPixel(x, y < height ? y : y - 1);
108 else
109 c = bm.GetPixel(x * 2, y < height ? y * 2 : y * 2 - 1);
110
111 redBytes[byteNdx] = c.R;
112 greenBytes[byteNdx] = c.G;
113 blueBytes[byteNdx] = c.B;
114
115 ++byteNdx;
116 }
117
118 if (smallMap)
119 c = bm.GetPixel(width - 1, y < height ? y : y - 1);
120 else
121 c = bm.GetPixel(width * 2 - 1, y < height ? y * 2 : y * 2 - 1);
122
123 redBytes[byteNdx] = c.R;
124 greenBytes[byteNdx] = c.G;
125 blueBytes[byteNdx] = c.B;
126
127 ++byteNdx;
128 }
129 }
130 catch (Exception e)
131 {
132 throw new Exception("Caught exception processing byte arrays in SculptMap(): e: " + e.ToString());
133 }
134
135 width++;
136 height++;
137 }
138
139 public List<List<Coord>> ToRows(bool mirror)
140 {
141 int numRows = height;
142 int numCols = width;
143
144 List<List<Coord>> rows = new List<List<Coord>>(numRows);
145
146 float pixScale = 1.0f / 255;
147
148 int rowNdx, colNdx;
149 int smNdx = 0;
150
151 for (rowNdx = 0; rowNdx < numRows; rowNdx++)
152 {
153 List<Coord> row = new List<Coord>(numCols);
154 for (colNdx = 0; colNdx < numCols; colNdx++)
155 {
156
157 if (mirror)
158 row.Add(new Coord(-((float)redBytes[smNdx] * pixScale - 0.5f), ((float)greenBytes[smNdx] * pixScale - 0.5f), (float)blueBytes[smNdx] * pixScale - 0.5f));
159 else
160 row.Add(new Coord((float)redBytes[smNdx] * pixScale - 0.5f, (float)greenBytes[smNdx] * pixScale - 0.5f, (float)blueBytes[smNdx] * pixScale - 0.5f));
161
162 ++smNdx;
163 }
164 rows.Add(row);
165 }
166 return rows;
167 }
168
169 private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight)
170 {
171
172 Bitmap scaledImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
173
174 Color c;
175
176
177 // will let last step to be eventually diferent, as seems to be in sl
178
179 float xscale = (float)srcImage.Width / (float)destWidth;
180 float yscale = (float)srcImage.Height / (float)destHeight;
181
182 int lastsx = srcImage.Width - 1;
183 int lastsy = srcImage.Height - 1;
184 int lastdx = destWidth - 1;
185 int lastdy = destHeight - 1;
186
187 float sy = 0.5f;
188 float sx;
189
190 for (int y = 0; y < lastdy; y++)
191 {
192 sx = 0.5f;
193 for (int x = 0; x < lastdx; x++)
194 {
195 try
196 {
197 c = srcImage.GetPixel((int)(sx), (int)(sy));
198 scaledImage.SetPixel(x, y, Color.FromArgb(c.R, c.G, c.B));
199 }
200 catch (IndexOutOfRangeException)
201 {
202 }
203 sx += xscale;
204 }
205 try
206 {
207 c = srcImage.GetPixel(lastsx, (int)(sy));
208 scaledImage.SetPixel(lastdx, y, Color.FromArgb(c.R, c.G, c.B));
209 }
210 catch (IndexOutOfRangeException)
211 {
212 }
213
214 sy += yscale;
215 }
216
217 sx = 0.5f;
218 for (int x = 0; x < lastdx; x++)
219 {
220 try
221 {
222 c = srcImage.GetPixel((int)(sx), lastsy);
223 scaledImage.SetPixel(x, lastdy, Color.FromArgb(c.R, c.G, c.B));
224 }
225 catch (IndexOutOfRangeException)
226 {
227 }
228
229 sx += xscale;
230 }
231 try
232 {
233 c = srcImage.GetPixel(lastsx, lastsy);
234 scaledImage.SetPixel(lastdx, lastdy, Color.FromArgb(c.R, c.G, c.B));
235 }
236 catch (IndexOutOfRangeException)
237 {
238 }
239
240 srcImage.Dispose();
241 return scaledImage;
242 }
243 }
244} \ No newline at end of file
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMesh.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMesh.cs
new file mode 100644
index 0000000..bc1375b
--- /dev/null
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/SculptMesh.cs
@@ -0,0 +1,220 @@
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 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;
31using System.IO;
32
33using System.Drawing;
34using System.Drawing.Imaging;
35
36namespace PrimMesher
37{
38
39 public class SculptMesh
40 {
41 public List<Coord> coords;
42 public List<Face> faces;
43
44 public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 };
45
46
47 public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool mirror, bool invert)
48 {
49 if (mirror)
50 invert = !invert;
51
52 SculptMap smap = new SculptMap(sculptBitmap, lod);
53
54 List<List<Coord>> rows = smap.ToRows(mirror);
55
56 _SculptMesh(rows, sculptType, invert);
57 }
58
59 private void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool invert)
60 {
61 coords = new List<Coord>();
62 faces = new List<Face>();
63
64 sculptType = (SculptType)(((int)sculptType) & 0x07);
65
66 int width = rows[0].Count;
67
68 int p1, p2, p3, p4;
69
70 int imageX, imageY;
71
72 if (sculptType != SculptType.plane)
73 {
74 if (rows.Count % 2 == 0)
75 {
76 for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++)
77 rows[rowNdx].Add(rows[rowNdx][0]);
78 }
79 else
80 {
81 int lastIndex = rows[0].Count - 1;
82
83 for (int i = 0; i < rows.Count; i++)
84 rows[i][0] = rows[i][lastIndex];
85 }
86 }
87
88 Coord topPole = rows[0][width / 2];
89 Coord bottomPole = rows[rows.Count - 1][width / 2];
90
91 if (sculptType == SculptType.sphere)
92 {
93 if (rows.Count % 2 == 0)
94 {
95 int count = rows[0].Count;
96 List<Coord> topPoleRow = new List<Coord>(count);
97 List<Coord> bottomPoleRow = new List<Coord>(count);
98
99 for (int i = 0; i < count; i++)
100 {
101 topPoleRow.Add(topPole);
102 bottomPoleRow.Add(bottomPole);
103 }
104 rows.Insert(0, topPoleRow);
105 rows.Add(bottomPoleRow);
106 }
107 else
108 {
109 int count = rows[0].Count;
110
111 List<Coord> topPoleRow = rows[0];
112 List<Coord> bottomPoleRow = rows[rows.Count - 1];
113
114 for (int i = 0; i < count; i++)
115 {
116 topPoleRow[i] = topPole;
117 bottomPoleRow[i] = bottomPole;
118 }
119 }
120 }
121
122 if (sculptType == SculptType.torus)
123 rows.Add(rows[0]);
124
125 int coordsDown = rows.Count;
126 int coordsAcross = rows[0].Count;
127
128 float widthUnit = 1.0f / (coordsAcross - 1);
129 float heightUnit = 1.0f / (coordsDown - 1);
130
131 for (imageY = 0; imageY < coordsDown; imageY++)
132 {
133 int rowOffset = imageY * coordsAcross;
134
135 for (imageX = 0; imageX < coordsAcross; imageX++)
136 {
137 /*
138 * p1-----p2
139 * | \ f2 |
140 * | \ |
141 * | f1 \|
142 * p3-----p4
143 */
144
145 p4 = rowOffset + imageX;
146 p3 = p4 - 1;
147
148 p2 = p4 - coordsAcross;
149 p1 = p3 - coordsAcross;
150
151 this.coords.Add(rows[imageY][imageX]);
152
153 if (imageY > 0 && imageX > 0)
154 {
155 Face f1, f2;
156
157 if (invert)
158 {
159 f1 = new Face(p1, p4, p3);
160 f2 = new Face(p1, p2, p4);
161 }
162 else
163 {
164 f1 = new Face(p1, p3, p4);
165 f2 = new Face(p1, p4, p2);
166 }
167
168 this.faces.Add(f1);
169 this.faces.Add(f2);
170 }
171 }
172 }
173 }
174
175 /// <summary>
176 /// Duplicates a SculptMesh object. All object properties are copied by value, including lists.
177 /// </summary>
178 /// <returns></returns>
179 public SculptMesh Copy()
180 {
181 return new SculptMesh(this);
182 }
183
184 public SculptMesh(SculptMesh sm)
185 {
186 coords = new List<Coord>(sm.coords);
187 faces = new List<Face>(sm.faces);
188 }
189
190 public void Scale(float x, float y, float z)
191 {
192 int i;
193 int numVerts = this.coords.Count;
194
195 Coord m = new Coord(x, y, z);
196 for (i = 0; i < numVerts; i++)
197 this.coords[i] *= m;
198 }
199
200 public void DumpRaw(String path, String name, String title)
201 {
202 if (path == null)
203 return;
204 String fileName = name + "_" + title + ".raw";
205 String completePath = System.IO.Path.Combine(path, fileName);
206 StreamWriter sw = new StreamWriter(completePath);
207
208 for (int i = 0; i < this.faces.Count; i++)
209 {
210 string s = this.coords[this.faces[i].v1].ToString();
211 s += " " + this.coords[this.faces[i].v2].ToString();
212 s += " " + this.coords[this.faces[i].v3].ToString();
213
214 sw.WriteLine(s);
215 }
216
217 sw.Close();
218 }
219 }
220}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 036cb5d..84d44a1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -28,9 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection;
32using System.Threading; 31using System.Threading;
33using log4net;
34using OpenMetaverse; 32using OpenMetaverse;
35using OpenSim.Framework; 33using OpenSim.Framework;
36using OpenSim.Framework.Monitoring; 34using OpenSim.Framework.Monitoring;
@@ -39,6 +37,8 @@ using OpenSim.Region.ScriptEngine.Interfaces;
39using OpenSim.Region.ScriptEngine.Shared; 37using OpenSim.Region.ScriptEngine.Shared;
40using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 38using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
41using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; 39using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
40using System.Reflection;
41using log4net;
42 42
43namespace OpenSim.Region.ScriptEngine.Shared.Api 43namespace OpenSim.Region.ScriptEngine.Shared.Api
44{ 44{
@@ -269,6 +269,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
269 /// <param name="itemID"></param> 269 /// <param name="itemID"></param>
270 public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID) 270 public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID)
271 { 271 {
272 // Remove a specific script
272// m_log.DebugFormat("[ASYNC COMMAND MANAGER]: Removing facilities for script {0}", itemID); 273// m_log.DebugFormat("[ASYNC COMMAND MANAGER]: Removing facilities for script {0}", itemID);
273 274
274 lock (staticLock) 275 lock (staticLock)
@@ -282,7 +283,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
282 // Remove from: HttpRequest 283 // Remove from: HttpRequest
283 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>(); 284 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>();
284 if (iHttpReq != null) 285 if (iHttpReq != null)
285 iHttpReq.StopHttpRequestsForScript(itemID); 286 iHttpReq.StopHttpRequest(localID, itemID);
286 287
287 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>(); 288 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
288 if (comms != null) 289 if (comms != null)
@@ -386,6 +387,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
386 } 387 }
387 } 388 }
388 389
390
391
389 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) 392 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID)
390 { 393 {
391 List<Object> data = new List<Object>(); 394 List<Object> data = new List<Object>();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs
new file mode 100644
index 0000000..81e30c9
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.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 System.Threading;
30using System.Reflection;
31using System.Collections;
32using System.Collections.Generic;
33using System.Runtime.Remoting.Lifetime;
34using OpenMetaverse;
35using Nini.Config;
36using OpenSim;
37using OpenSim.Framework;
38using OpenSim.Region.CoreModules.World.LightShare;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.ScriptEngine.Shared;
42using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
43using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
44using OpenSim.Region.ScriptEngine.Interfaces;
45using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
46using OpenSim.Services.Interfaces;
47
48using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
49using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
50using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
51using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
52using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
53using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
54using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
55
56namespace OpenSim.Region.ScriptEngine.Shared.Api
57{
58 [Serializable]
59 public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi
60 {
61 internal IScriptEngine m_ScriptEngine;
62 internal SceneObjectPart m_host;
63 internal TaskInventoryItem m_item;
64 internal bool m_CMFunctionsEnabled = false;
65
66 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
67 {
68 m_ScriptEngine = ScriptEngine;
69 m_host = host;
70 m_item = item;
71
72 if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false))
73 m_CMFunctionsEnabled = true;
74 }
75
76 public override Object InitializeLifetimeService()
77 {
78 ILease lease = (ILease)base.InitializeLifetimeService();
79
80 if (lease.CurrentState == LeaseState.Initial)
81 {
82 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
83// lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
84// lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
85 }
86 return lease;
87 }
88
89 public Scene World
90 {
91 get { return m_ScriptEngine.World; }
92 }
93
94 public string cmDetectedCountry(int number)
95 {
96 m_host.AddScriptLPS(1);
97 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
98 if (detectedParams == null)
99 return String.Empty;
100 return detectedParams.Country;
101 }
102
103 public string cmGetAgentCountry(LSL_Key key)
104 {
105 if (!World.Permissions.IsGod(m_host.OwnerID))
106 return String.Empty;
107
108 UUID uuid;
109
110 if (!UUID.TryParse(key, out uuid))
111 return String.Empty;
112
113 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
114 return account.UserCountry;
115 }
116 }
117}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 4eda443..f9f21f1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -35,10 +35,12 @@ using System.Runtime.Remoting.Lifetime;
35using System.Text; 35using System.Text;
36using System.Threading; 36using System.Threading;
37using System.Text.RegularExpressions; 37using System.Text.RegularExpressions;
38using System.Timers;
38using Nini.Config; 39using Nini.Config;
39using log4net; 40using log4net;
40using OpenMetaverse; 41using OpenMetaverse;
41using OpenMetaverse.Assets; 42using OpenMetaverse.Assets;
43using OpenMetaverse.StructuredData;
42using OpenMetaverse.Packets; 44using OpenMetaverse.Packets;
43using OpenMetaverse.Rendering; 45using OpenMetaverse.Rendering;
44using OpenSim; 46using OpenSim;
@@ -49,6 +51,7 @@ using OpenSim.Region.CoreModules.World.Land;
49using OpenSim.Region.CoreModules.World.Terrain; 51using OpenSim.Region.CoreModules.World.Terrain;
50using OpenSim.Region.Framework.Interfaces; 52using OpenSim.Region.Framework.Interfaces;
51using OpenSim.Region.Framework.Scenes; 53using OpenSim.Region.Framework.Scenes;
54using OpenSim.Region.Framework.Scenes.Serialization;
52using OpenSim.Region.Framework.Scenes.Animation; 55using OpenSim.Region.Framework.Scenes.Animation;
53using OpenSim.Region.Framework.Scenes.Scripting; 56using OpenSim.Region.Framework.Scenes.Scripting;
54using OpenSim.Region.PhysicsModules.SharedBase; 57using OpenSim.Region.PhysicsModules.SharedBase;
@@ -72,6 +75,7 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
72using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 75using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
73using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 76using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
74using System.Reflection; 77using System.Reflection;
78using Timer = System.Timers.Timer;
75using System.Linq; 79using System.Linq;
76using PermissionMask = OpenSim.Framework.PermissionMask; 80using PermissionMask = OpenSim.Framework.PermissionMask;
77 81
@@ -120,7 +124,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
120 protected int m_notecardLineReadCharsMax = 255; 124 protected int m_notecardLineReadCharsMax = 255;
121 protected int m_scriptConsoleChannel = 0; 125 protected int m_scriptConsoleChannel = 0;
122 protected bool m_scriptConsoleChannelEnabled = false; 126 protected bool m_scriptConsoleChannelEnabled = false;
127 protected bool m_debuggerSafe = false;
123 protected IUrlModule m_UrlModule = null; 128 protected IUrlModule m_UrlModule = null;
129
124 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 130 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>();
125 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 131 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
126 protected int m_sleepMsOnSetTexture = 200; 132 protected int m_sleepMsOnSetTexture = 200;
@@ -242,6 +248,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
242 protected bool m_useMeshCacheInCastRay = true; 248 protected bool m_useMeshCacheInCastRay = true;
243 protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>(); 249 protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>();
244 250
251// protected Timer m_ShoutSayTimer;
252 protected int m_SayShoutCount = 0;
253 DateTime m_lastSayShoutCheck;
254
255 private Dictionary<string, string> MovementAnimationsForLSL =
256 new Dictionary<string, string> {
257 {"CROUCH", "Crouching"},
258 {"CROUCHWALK", "CrouchWalking"},
259 {"FALLDOWN", "Falling Down"},
260 {"FLY", "Flying"},
261 {"FLYSLOW", "FlyingSlow"},
262 {"HOVER", "Hovering"},
263 {"HOVER_UP", "Hovering Up"},
264 {"HOVER_DOWN", "Hovering Down"},
265 {"JUMP", "Jumping"},
266 {"LAND", "Landing"},
267 {"PREJUMP", "PreJumping"},
268 {"RUN", "Running"},
269 {"SIT","Sitting"},
270 {"SITGROUND","Sitting on Ground"},
271 {"STAND", "Standing"},
272 {"STANDUP", "Standing Up"},
273 {"STRIDE","Striding"},
274 {"SOFT_LAND", "Soft Landing"},
275 {"TURNLEFT", "Turning Left"},
276 {"TURNRIGHT", "Turning Right"},
277 {"WALK", "Walking"}
278 };
279
245 //An array of HTTP/1.1 headers that are not allowed to be used 280 //An array of HTTP/1.1 headers that are not allowed to be used
246 //as custom headers by llHTTPRequest. 281 //as custom headers by llHTTPRequest.
247 private string[] HttpStandardHeaders = 282 private string[] HttpStandardHeaders =
@@ -262,10 +297,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
262 public void Initialize( 297 public void Initialize(
263 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item) 298 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
264 { 299 {
300 m_lastSayShoutCheck = DateTime.UtcNow;
301
265 m_ScriptEngine = scriptEngine; 302 m_ScriptEngine = scriptEngine;
266 m_host = host; 303 m_host = host;
267 m_item = item; 304 m_item = item;
268 305 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
306
269 LoadConfig(); 307 LoadConfig();
270 308
271 m_TransferModule = 309 m_TransferModule =
@@ -422,6 +460,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
422 get { return m_ScriptEngine.World; } 460 get { return m_ScriptEngine.World; }
423 } 461 }
424 462
463 [DebuggerNonUserCode]
425 public void state(string newState) 464 public void state(string newState)
426 { 465 {
427 m_ScriptEngine.SetState(m_item.ItemID, newState); 466 m_ScriptEngine.SetState(m_item.ItemID, newState);
@@ -431,6 +470,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
431 /// Reset the named script. The script must be present 470 /// Reset the named script. The script must be present
432 /// in the same prim. 471 /// in the same prim.
433 /// </summary> 472 /// </summary>
473 [DebuggerNonUserCode]
434 public void llResetScript() 474 public void llResetScript()
435 { 475 {
436 m_host.AddScriptLPS(1); 476 m_host.AddScriptLPS(1);
@@ -493,6 +533,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
493 } 533 }
494 } 534 }
495 535
536 public List<ScenePresence> GetLinkAvatars(int linkType)
537 {
538 List<ScenePresence> ret = new List<ScenePresence>();
539 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
540 return ret;
541
542 // List<ScenePresence> avs = m_host.ParentGroup.GetLinkedAvatars();
543 // this needs check
544 List<ScenePresence> avs = m_host.ParentGroup.GetSittingAvatars();
545 switch (linkType)
546 {
547 case ScriptBaseClass.LINK_SET:
548 return avs;
549
550 case ScriptBaseClass.LINK_ROOT:
551 return ret;
552
553 case ScriptBaseClass.LINK_ALL_OTHERS:
554 return avs;
555
556 case ScriptBaseClass.LINK_ALL_CHILDREN:
557 return avs;
558
559 case ScriptBaseClass.LINK_THIS:
560 return ret;
561
562 default:
563 if (linkType < 0)
564 return ret;
565
566 int partCount = m_host.ParentGroup.GetPartCount();
567
568 if (linkType <= partCount)
569 {
570 return ret;
571 }
572 else
573 {
574 linkType = linkType - partCount;
575 if (linkType > avs.Count)
576 {
577 return ret;
578 }
579 else
580 {
581 ret.Add(avs[linkType-1]);
582 return ret;
583 }
584 }
585 }
586 }
587
496 /// <summary> 588 /// <summary>
497 /// Get a given link entity from a linkset (linked objects and any sitting avatars). 589 /// Get a given link entity from a linkset (linked objects and any sitting avatars).
498 /// </summary> 590 /// </summary>
@@ -572,6 +664,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
572 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 664 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
573 { 665 {
574 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 666 List<SceneObjectPart> ret = new List<SceneObjectPart>();
667 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
668 return ret;
575 ret.Add(part); 669 ret.Add(part);
576 670
577 switch (linkType) 671 switch (linkType)
@@ -719,8 +813,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
719 public LSL_Float llFrand(double mag) 813 public LSL_Float llFrand(double mag)
720 { 814 {
721 m_host.AddScriptLPS(1); 815 m_host.AddScriptLPS(1);
722 816 lock (Util.RandomClass)
723 return Util.RandomClass.NextDouble() * mag; 817 {
818 return Util.RandomClass.NextDouble() * mag;
819 }
724 } 820 }
725 821
726 public LSL_Integer llFloor(double f) 822 public LSL_Integer llFloor(double f)
@@ -771,31 +867,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
771 867
772 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 868 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
773 869
774 /// <summary> 870 // Utility function for llRot2Euler
775 /// Convert an LSL rotation to a Euler vector. 871
776 /// </summary> 872 public LSL_Vector llRot2Euler(LSL_Rotation q1)
777 /// <remarks>
778 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
779 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
780 /// </remarks>
781 /// <param name="r"></param>
782 /// <returns></returns>
783 public LSL_Vector llRot2Euler(LSL_Rotation r)
784 { 873 {
785 m_host.AddScriptLPS(1); 874 m_host.AddScriptLPS(1);
875 LSL_Vector eul = new LSL_Vector();
786 876
787 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 877 double sqw = q1.s*q1.s;
788 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 878 double sqx = q1.x*q1.x;
789 if (m == 0.0) return new LSL_Vector(); 879 double sqy = q1.z*q1.z;
790 double x = Math.Atan2(-v.y, v.z); 880 double sqz = q1.y*q1.y;
791 double sin = v.x / m; 881 double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
792 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 882 double test = q1.x*q1.z + q1.y*q1.s;
793 double y = Math.Asin(sin); 883 if (test > 0.4999*unit) { // singularity at north pole
794 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation 884 eul.z = 2 * Math.Atan2(q1.x,q1.s);
795 v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0))); 885 eul.y = Math.PI/2;
796 double z = Math.Atan2(v.y, v.x); 886 eul.x = 0;
797 887 return eul;
798 return new LSL_Vector(x, y, z); 888 }
889 if (test < -0.4999*unit) { // singularity at south pole
890 eul.z = -2 * Math.Atan2(q1.x,q1.s);
891 eul.y = -Math.PI/2;
892 eul.x = 0;
893 return eul;
894 }
895 eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw);
896 eul.y = Math.Asin(2*test/unit);
897 eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw);
898 return eul;
799 } 899 }
800 900
801 /* From wiki: 901 /* From wiki:
@@ -848,18 +948,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
848 m_host.AddScriptLPS(1); 948 m_host.AddScriptLPS(1);
849 949
850 double x,y,z,s; 950 double x,y,z,s;
851 951 v.x *= 0.5;
852 double c1 = Math.Cos(v.x * 0.5); 952 v.y *= 0.5;
853 double c2 = Math.Cos(v.y * 0.5); 953 v.z *= 0.5;
854 double c3 = Math.Cos(v.z * 0.5); 954 double c1 = Math.Cos(v.x);
855 double s1 = Math.Sin(v.x * 0.5); 955 double c2 = Math.Cos(v.y);
856 double s2 = Math.Sin(v.y * 0.5); 956 double c1c2 = c1 * c2;
857 double s3 = Math.Sin(v.z * 0.5); 957 double s1 = Math.Sin(v.x);
858 958 double s2 = Math.Sin(v.y);
859 x = s1 * c2 * c3 + c1 * s2 * s3; 959 double s1s2 = s1 * s2;
860 y = c1 * s2 * c3 - s1 * c2 * s3; 960 double c1s2 = c1 * s2;
861 z = s1 * s2 * c3 + c1 * c2 * s3; 961 double s1c2 = s1 * c2;
862 s = c1 * c2 * c3 - s1 * s2 * s3; 962 double c3 = Math.Cos(v.z);
963 double s3 = Math.Sin(v.z);
964
965 x = s1c2 * c3 + c1s2 * s3;
966 y = c1s2 * c3 - s1c2 * s3;
967 z = s1s2 * c3 + c1c2 * s3;
968 s = c1c2 * c3 - s1s2 * s3;
863 969
864 return new LSL_Rotation(x, y, z, s); 970 return new LSL_Rotation(x, y, z, s);
865 } 971 }
@@ -997,77 +1103,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
997 { 1103 {
998 //A and B should both be normalized 1104 //A and B should both be normalized
999 m_host.AddScriptLPS(1); 1105 m_host.AddScriptLPS(1);
1000 LSL_Rotation rotBetween; 1106 /* This method is more accurate than the SL one, and thus causes problems
1001 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 1107 for scripts that deal with the SL inaccuracy around 180-degrees -.- .._.
1002 // continue calculation. 1108
1003 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 1109 double dotProduct = LSL_Vector.Dot(a, b);
1110 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
1111 double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b);
1112 double angle = Math.Acos(dotProduct / magProduct);
1113 LSL_Vector axis = LSL_Vector.Norm(crossProduct);
1114 double s = Math.Sin(angle / 2);
1115
1116 double x = axis.x * s;
1117 double y = axis.y * s;
1118 double z = axis.z * s;
1119 double w = Math.Cos(angle / 2);
1120
1121 if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w))
1122 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1123
1124 return new LSL_Rotation((float)x, (float)y, (float)z, (float)w);
1125 */
1126
1127 // This method mimics the 180 errors found in SL
1128 // See www.euclideanspace.com... angleBetween
1129 LSL_Vector vec_a = a;
1130 LSL_Vector vec_b = b;
1131
1132 // Eliminate zero length
1133 LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a);
1134 LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b);
1135 if (vec_a_mag < 0.00001 ||
1136 vec_b_mag < 0.00001)
1004 { 1137 {
1005 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 1138 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1006 } 1139 }
1007 else 1140
1141 // Normalize
1142 vec_a = llVecNorm(vec_a);
1143 vec_b = llVecNorm(vec_b);
1144
1145 // Calculate axis and rotation angle
1146 LSL_Vector axis = vec_a % vec_b;
1147 LSL_Float cos_theta = vec_a * vec_b;
1148
1149 // Check if parallel
1150 if (cos_theta > 0.99999)
1008 { 1151 {
1009 a = LSL_Vector.Norm(a); 1152 return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1010 b = LSL_Vector.Norm(b); 1153 }
1011 double dotProduct = LSL_Vector.Dot(a, b); 1154
1012 // There are two degenerate cases possible. These are for vectors 180 or 1155 // Check if anti-parallel
1013 // 0 degrees apart. These have to be detected and handled individually. 1156 else if (cos_theta < -0.99999)
1014 // 1157 {
1015 // Check for vectors 180 degrees apart. 1158 LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a);
1016 // A dot product of -1 would mean the angle between vectors is 180 degrees. 1159 if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0);
1017 if (dotProduct < -0.9999999f) 1160 return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0);
1018 { 1161 }
1019 // First assume X axis is orthogonal to the vectors. 1162 else // other rotation
1020 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 1163 {
1021 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 1164 LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f;
1022 // Check for near zero vector. A very small non-zero number here will create 1165 axis = llVecNorm(axis);
1023 // a rotation in an undesired direction. 1166 double x, y, z, s, t;
1024 if (LSL_Vector.Mag(orthoVector) > 0.0001) 1167 s = Math.Cos(theta);
1025 { 1168 t = Math.Sin(theta);
1026 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 1169 x = axis.x * t;
1027 } 1170 y = axis.y * t;
1028 // If the magnitude of the vector was near zero, then assume the X axis is not 1171 z = axis.z * t;
1029 // orthogonal and use the Z axis instead. 1172 return new LSL_Rotation(x,y,z,s);
1030 else
1031 {
1032 // Set 180 z rotation.
1033 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
1034 }
1035 }
1036 // Check for parallel vectors.
1037 // A dot product of 1 would mean the angle between vectors is 0 degrees.
1038 else if (dotProduct > 0.9999999f)
1039 {
1040 // Set zero rotation.
1041 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1042 }
1043 else
1044 {
1045 // All special checks have been performed so get the axis of rotation.
1046 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
1047 // Quarternion s value is the length of the unit vector + dot product.
1048 double qs = 1.0 + dotProduct;
1049 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
1050 // Normalize the rotation.
1051 double mag = LSL_Rotation.Mag(rotBetween);
1052 // We shouldn't have to worry about a divide by zero here. The qs value will be
1053 // non-zero because we already know if we're here, then the dotProduct is not -1 so
1054 // qs will not be zero. Also, we've already handled the input vectors being zero so the
1055 // crossProduct vector should also not be zero.
1056 rotBetween.x = rotBetween.x / mag;
1057 rotBetween.y = rotBetween.y / mag;
1058 rotBetween.z = rotBetween.z / mag;
1059 rotBetween.s = rotBetween.s / mag;
1060 // Check for undefined values and set zero rotation if any found. This code might not actually be required
1061 // any longer since zero vectors are checked for at the top.
1062 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
1063 {
1064 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1065 }
1066 }
1067 } 1173 }
1068 return rotBetween;
1069 } 1174 }
1070 1175
1071 public void llWhisper(int channelID, string text) 1176 public void llWhisper(int channelID, string text)
1072 { 1177 {
1073 m_host.AddScriptLPS(1); 1178 m_host.AddScriptLPS(1);
@@ -1083,10 +1188,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1083 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); 1188 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
1084 } 1189 }
1085 1190
1191 private void CheckSayShoutTime()
1192 {
1193 DateTime now = DateTime.UtcNow;
1194 if ((now - m_lastSayShoutCheck).Ticks > 10000000) // 1sec
1195 {
1196 m_lastSayShoutCheck = now;
1197 m_SayShoutCount = 0;
1198 }
1199 else
1200 m_SayShoutCount++;
1201 }
1202
1086 public void llSay(int channelID, string text) 1203 public void llSay(int channelID, string text)
1087 { 1204 {
1088 m_host.AddScriptLPS(1); 1205 m_host.AddScriptLPS(1);
1089 1206
1207 if (channelID == 0)
1208// m_SayShoutCount++;
1209 CheckSayShoutTime();
1210
1211 if (m_SayShoutCount >= 11)
1212 ScriptSleep(2000);
1213
1090 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 1214 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
1091 { 1215 {
1092 Console.WriteLine(text); 1216 Console.WriteLine(text);
@@ -1109,6 +1233,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1109 { 1233 {
1110 m_host.AddScriptLPS(1); 1234 m_host.AddScriptLPS(1);
1111 1235
1236 if (channelID == 0)
1237// m_SayShoutCount++;
1238 CheckSayShoutTime();
1239
1240 if (m_SayShoutCount >= 11)
1241 ScriptSleep(2000);
1242
1112 if (text.Length > 1023) 1243 if (text.Length > 1023)
1113 text = text.Substring(0, 1023); 1244 text = text.Substring(0, 1023);
1114 1245
@@ -1417,10 +1548,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1417 return detectedParams.TouchUV; 1548 return detectedParams.TouchUV;
1418 } 1549 }
1419 1550
1551 [DebuggerNonUserCode]
1420 public virtual void llDie() 1552 public virtual void llDie()
1421 { 1553 {
1422 m_host.AddScriptLPS(1); 1554 m_host.AddScriptLPS(1);
1423 throw new SelfDeleteException(); 1555 if (!m_host.ParentGroup.IsAttachment) throw new SelfDeleteException();
1424 } 1556 }
1425 1557
1426 public LSL_Float llGround(LSL_Vector offset) 1558 public LSL_Float llGround(LSL_Vector offset)
@@ -1491,6 +1623,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1491 1623
1492 public void llSetStatus(int status, int value) 1624 public void llSetStatus(int status, int value)
1493 { 1625 {
1626 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted)
1627 return;
1494 m_host.AddScriptLPS(1); 1628 m_host.AddScriptLPS(1);
1495 1629
1496 int statusrotationaxis = 0; 1630 int statusrotationaxis = 0;
@@ -1502,6 +1636,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1502 SceneObjectGroup group = m_host.ParentGroup; 1636 SceneObjectGroup group = m_host.ParentGroup;
1503 bool allow = true; 1637 bool allow = true;
1504 1638
1639 int maxprims = World.m_linksetPhysCapacity;
1640 bool checkShape = (maxprims > 0 && group.PrimCount > maxprims);
1641
1505 foreach (SceneObjectPart part in group.Parts) 1642 foreach (SceneObjectPart part in group.Parts)
1506 { 1643 {
1507 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) 1644 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
@@ -1509,11 +1646,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1509 allow = false; 1646 allow = false;
1510 break; 1647 break;
1511 } 1648 }
1649 if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None)
1650 {
1651 if (--maxprims < 0)
1652 {
1653 allow = false;
1654 break;
1655 }
1656 }
1512 } 1657 }
1513 1658
1514 if (!allow) 1659 if (!allow)
1515 return; 1660 return;
1516 1661
1662 if (m_host.ParentGroup.RootPart.PhysActor != null &&
1663 m_host.ParentGroup.RootPart.PhysActor.IsPhysical)
1664 return;
1665
1517 m_host.ScriptSetPhysicsStatus(true); 1666 m_host.ScriptSetPhysicsStatus(true);
1518 } 1667 }
1519 else 1668 else
@@ -1712,6 +1861,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1712 { 1861 {
1713 m_host.AddScriptLPS(1); 1862 m_host.AddScriptLPS(1);
1714 1863
1864 SetColor(m_host, color, face);
1865 }
1866
1867 protected void SetColor(SceneObjectPart part, LSL_Vector color, int face)
1868 {
1869 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1870 return;
1871
1872 Primitive.TextureEntry tex = part.Shape.Textures;
1873 Color4 texcolor;
1874 if (face >= 0 && face < GetNumberOfSides(part))
1875 {
1876 texcolor = tex.CreateFace((uint)face).RGBA;
1877 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1878 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1879 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1880 tex.FaceTextures[face].RGBA = texcolor;
1881 part.UpdateTextureEntry(tex.GetBytes());
1882 return;
1883 }
1884 else if (face == ScriptBaseClass.ALL_SIDES)
1885 {
1886 for (uint i = 0; i < GetNumberOfSides(part); i++)
1887 {
1888 if (tex.FaceTextures[i] != null)
1889 {
1890 texcolor = tex.FaceTextures[i].RGBA;
1891 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1892 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1893 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1894 tex.FaceTextures[i].RGBA = texcolor;
1895 }
1896 texcolor = tex.DefaultTexture.RGBA;
1897 texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
1898 texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
1899 texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
1900 tex.DefaultTexture.RGBA = texcolor;
1901 }
1902 part.UpdateTextureEntry(tex.GetBytes());
1903 return;
1904 }
1905
1715 if (face == ScriptBaseClass.ALL_SIDES) 1906 if (face == ScriptBaseClass.ALL_SIDES)
1716 face = SceneObjectPart.ALL_SIDES; 1907 face = SceneObjectPart.ALL_SIDES;
1717 1908
@@ -1737,7 +1928,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1737 string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent"); 1928 string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent");
1738 if (userAgent.IndexOf("SecondLife") < 0) 1929 if (userAgent.IndexOf("SecondLife") < 0)
1739 return; // Not the embedded browser. Is this check good enough? 1930 return; // Not the embedded browser. Is this check good enough?
1740 1931
1741 // Use the IP address of the client and check against the request 1932 // Use the IP address of the client and check against the request
1742 // seperate logins from the same IP will allow all of them to get non-text/plain as long 1933 // seperate logins from the same IP will allow all of them to get non-text/plain as long
1743 // as the owner is in the region. Same as SL! 1934 // as the owner is in the region. Same as SL!
@@ -1785,8 +1976,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1785 } 1976 }
1786 } 1977 }
1787 1978
1979/*
1980 public void llSetContentType(LSL_Key id, LSL_Integer content_type)
1981 {
1982 if (m_UrlModule != null)
1983 {
1984 string type = "text.plain";
1985 if (content_type == (int)ScriptBaseClass.CONTENT_TYPE_HTML)
1986 type = "text/html";
1987
1988 m_UrlModule.HttpContentType(new UUID(id),type);
1989 }
1990 }
1991*/
1788 public void SetTexGen(SceneObjectPart part, int face,int style) 1992 public void SetTexGen(SceneObjectPart part, int face,int style)
1789 { 1993 {
1994 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
1995 return;
1996
1790 Primitive.TextureEntry tex = part.Shape.Textures; 1997 Primitive.TextureEntry tex = part.Shape.Textures;
1791 MappingType textype; 1998 MappingType textype;
1792 textype = MappingType.Default; 1999 textype = MappingType.Default;
@@ -1817,6 +2024,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1817 2024
1818 public void SetGlow(SceneObjectPart part, int face, float glow) 2025 public void SetGlow(SceneObjectPart part, int face, float glow)
1819 { 2026 {
2027 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2028 return;
2029
1820 Primitive.TextureEntry tex = part.Shape.Textures; 2030 Primitive.TextureEntry tex = part.Shape.Textures;
1821 if (face >= 0 && face < GetNumberOfSides(part)) 2031 if (face >= 0 && face < GetNumberOfSides(part))
1822 { 2032 {
@@ -1842,6 +2052,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1842 2052
1843 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 2053 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1844 { 2054 {
2055 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2056 return;
1845 2057
1846 Shininess sval = new Shininess(); 2058 Shininess sval = new Shininess();
1847 2059
@@ -1892,6 +2104,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1892 2104
1893 public void SetFullBright(SceneObjectPart part, int face, bool bright) 2105 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1894 { 2106 {
2107 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2108 return;
2109
1895 Primitive.TextureEntry tex = part.Shape.Textures; 2110 Primitive.TextureEntry tex = part.Shape.Textures;
1896 if (face >= 0 && face < GetNumberOfSides(part)) 2111 if (face >= 0 && face < GetNumberOfSides(part))
1897 { 2112 {
@@ -1952,13 +2167,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1952 m_host.AddScriptLPS(1); 2167 m_host.AddScriptLPS(1);
1953 2168
1954 List<SceneObjectPart> parts = GetLinkParts(linknumber); 2169 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1955 2170 if (parts.Count > 0)
1956 foreach (SceneObjectPart part in parts) 2171 {
1957 SetAlpha(part, alpha, face); 2172 try
2173 {
2174 foreach (SceneObjectPart part in parts)
2175 SetAlpha(part, alpha, face);
2176 }
2177 finally { }
2178 }
1958 } 2179 }
1959 2180
1960 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 2181 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1961 { 2182 {
2183 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2184 return;
2185
1962 Primitive.TextureEntry tex = part.Shape.Textures; 2186 Primitive.TextureEntry tex = part.Shape.Textures;
1963 Color4 texcolor; 2187 Color4 texcolor;
1964 if (face >= 0 && face < GetNumberOfSides(part)) 2188 if (face >= 0 && face < GetNumberOfSides(part))
@@ -2011,7 +2235,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2011 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 2235 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
2012 float wind, float tension, LSL_Vector Force) 2236 float wind, float tension, LSL_Vector Force)
2013 { 2237 {
2014 if (part == null) 2238 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2015 return; 2239 return;
2016 2240
2017 if (flexi) 2241 if (flexi)
@@ -2052,7 +2276,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2052 /// <param name="falloff"></param> 2276 /// <param name="falloff"></param>
2053 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 2277 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
2054 { 2278 {
2055 if (part == null) 2279 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2056 return; 2280 return;
2057 2281
2058 if (light) 2282 if (light)
@@ -2085,11 +2309,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2085 Primitive.TextureEntry tex = part.Shape.Textures; 2309 Primitive.TextureEntry tex = part.Shape.Textures;
2086 Color4 texcolor; 2310 Color4 texcolor;
2087 LSL_Vector rgb = new LSL_Vector(); 2311 LSL_Vector rgb = new LSL_Vector();
2312 int nsides = GetNumberOfSides(part);
2313
2088 if (face == ScriptBaseClass.ALL_SIDES) 2314 if (face == ScriptBaseClass.ALL_SIDES)
2089 { 2315 {
2090 int i; 2316 int i;
2091 2317 for (i = 0; i < nsides; i++)
2092 for (i = 0 ; i < GetNumberOfSides(part); i++)
2093 { 2318 {
2094 texcolor = tex.GetFace((uint)i).RGBA; 2319 texcolor = tex.GetFace((uint)i).RGBA;
2095 rgb.x += texcolor.R; 2320 rgb.x += texcolor.R;
@@ -2097,14 +2322,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2097 rgb.z += texcolor.B; 2322 rgb.z += texcolor.B;
2098 } 2323 }
2099 2324
2100 rgb.x /= (float)GetNumberOfSides(part); 2325 float invnsides = 1.0f / (float)nsides;
2101 rgb.y /= (float)GetNumberOfSides(part); 2326
2102 rgb.z /= (float)GetNumberOfSides(part); 2327 rgb.x *= invnsides;
2328 rgb.y *= invnsides;
2329 rgb.z *= invnsides;
2103 2330
2104 return rgb; 2331 return rgb;
2105 } 2332 }
2106 2333 if (face >= 0 && face < nsides)
2107 if (face >= 0 && face < GetNumberOfSides(part))
2108 { 2334 {
2109 texcolor = tex.GetFace((uint)face).RGBA; 2335 texcolor = tex.GetFace((uint)face).RGBA;
2110 rgb.x = texcolor.R; 2336 rgb.x = texcolor.R;
@@ -2131,15 +2357,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2131 m_host.AddScriptLPS(1); 2357 m_host.AddScriptLPS(1);
2132 2358
2133 List<SceneObjectPart> parts = GetLinkParts(linknumber); 2359 List<SceneObjectPart> parts = GetLinkParts(linknumber);
2134 2360 if (parts.Count > 0)
2135 foreach (SceneObjectPart part in parts) 2361 {
2136 SetTexture(part, texture, face); 2362 try
2137 2363 {
2364 foreach (SceneObjectPart part in parts)
2365 SetTexture(part, texture, face);
2366 }
2367 finally { }
2368 }
2138 ScriptSleep(m_sleepMsOnSetLinkTexture); 2369 ScriptSleep(m_sleepMsOnSetLinkTexture);
2139 } 2370 }
2140 2371
2141 protected void SetTexture(SceneObjectPart part, string texture, int face) 2372 protected void SetTexture(SceneObjectPart part, string texture, int face)
2142 { 2373 {
2374 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2375 return;
2376
2143 UUID textureID = new UUID(); 2377 UUID textureID = new UUID();
2144 2378
2145 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); 2379 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
@@ -2184,6 +2418,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2184 2418
2185 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2419 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
2186 { 2420 {
2421 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2422 return;
2423
2187 Primitive.TextureEntry tex = part.Shape.Textures; 2424 Primitive.TextureEntry tex = part.Shape.Textures;
2188 if (face >= 0 && face < GetNumberOfSides(part)) 2425 if (face >= 0 && face < GetNumberOfSides(part))
2189 { 2426 {
@@ -2220,6 +2457,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2220 2457
2221 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2458 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
2222 { 2459 {
2460 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2461 return;
2462
2223 Primitive.TextureEntry tex = part.Shape.Textures; 2463 Primitive.TextureEntry tex = part.Shape.Textures;
2224 if (face >= 0 && face < GetNumberOfSides(part)) 2464 if (face >= 0 && face < GetNumberOfSides(part))
2225 { 2465 {
@@ -2256,6 +2496,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2256 2496
2257 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2497 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
2258 { 2498 {
2499 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2500 return;
2501
2259 Primitive.TextureEntry tex = part.Shape.Textures; 2502 Primitive.TextureEntry tex = part.Shape.Textures;
2260 if (face >= 0 && face < GetNumberOfSides(part)) 2503 if (face >= 0 && face < GetNumberOfSides(part))
2261 { 2504 {
@@ -2397,7 +2640,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2397 return end; 2640 return end;
2398 } 2641 }
2399 2642
2400 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos) 2643 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos, bool adjust)
2401 { 2644 {
2402 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 2645 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2403 return fromPos; 2646 return fromPos;
@@ -2413,9 +2656,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2413 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) 2656 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2414 targetPos.z = ground; 2657 targetPos.z = ground;
2415 } 2658 }
2416 LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos); 2659 if (adjust)
2660 return SetPosAdjust(fromPos, targetPos);
2417 2661
2418 return real_vec; 2662 return targetPos;
2419 } 2663 }
2420 2664
2421 /// <summary> 2665 /// <summary>
@@ -2426,27 +2670,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2426 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param> 2670 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
2427 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) 2671 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2428 { 2672 {
2429 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2673 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2674 return;
2675
2430 LSL_Vector currentPos = GetPartLocalPos(part); 2676 LSL_Vector currentPos = GetPartLocalPos(part);
2677 LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos, adjust);
2431 2678
2432 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2433 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
2434 2679
2435 if (part.ParentGroup.RootPart == part) 2680 if (part.ParentGroup.RootPart == part)
2436 { 2681 {
2437 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2438 targetPos.z = ground;
2439 SceneObjectGroup parent = part.ParentGroup; 2682 SceneObjectGroup parent = part.ParentGroup;
2440 parent.UpdateGroupPosition(!adjust ? targetPos : 2683 if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos))
2441 SetPosAdjust(currentPos, targetPos)); 2684 return;
2685 parent.UpdateGroupPosition((Vector3)toPos);
2442 } 2686 }
2443 else 2687 else
2444 { 2688 {
2445 part.OffsetPosition = !adjust ? targetPos : 2689 part.OffsetPosition = (Vector3)toPos;
2446 SetPosAdjust(currentPos, targetPos); 2690// SceneObjectGroup parent = part.ParentGroup;
2447 SceneObjectGroup parent = part.ParentGroup; 2691// parent.HasGroupChanged = true;
2448 parent.HasGroupChanged = true; 2692// parent.ScheduleGroupForTerseUpdate();
2449 parent.ScheduleGroupForTerseUpdate(); 2693 part.ScheduleTerseUpdate();
2450 } 2694 }
2451 } 2695 }
2452 2696
@@ -2475,13 +2719,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2475 else 2719 else
2476 { 2720 {
2477 if (part.ParentGroup.IsAttachment) 2721 if (part.ParentGroup.IsAttachment)
2478 {
2479 pos = part.AttachedPos; 2722 pos = part.AttachedPos;
2480 }
2481 else 2723 else
2482 {
2483 pos = part.AbsolutePosition; 2724 pos = part.AbsolutePosition;
2484 }
2485 } 2725 }
2486 2726
2487// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); 2727// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
@@ -2492,9 +2732,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2492 public void llSetRot(LSL_Rotation rot) 2732 public void llSetRot(LSL_Rotation rot)
2493 { 2733 {
2494 m_host.AddScriptLPS(1); 2734 m_host.AddScriptLPS(1);
2495 2735
2496 // try to let this work as in SL... 2736 // try to let this work as in SL...
2497 if (m_host.ParentID == 0) 2737 if (m_host.ParentID == 0 || (m_host.ParentGroup != null && m_host == m_host.ParentGroup.RootPart))
2498 { 2738 {
2499 // special case: If we are root, rotate complete SOG to new rotation 2739 // special case: If we are root, rotate complete SOG to new rotation
2500 SetRot(m_host, rot); 2740 SetRot(m_host, rot);
@@ -2521,25 +2761,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2521 2761
2522 protected void SetRot(SceneObjectPart part, Quaternion rot) 2762 protected void SetRot(SceneObjectPart part, Quaternion rot)
2523 { 2763 {
2524 part.UpdateRotation(rot); 2764 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2525 // Update rotation does not move the object in the physics scene if it's a linkset. 2765 return;
2526 2766
2527//KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type 2767 bool isroot = (part == part.ParentGroup.RootPart);
2528// part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; 2768 bool isphys;
2529 2769
2530 // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
2531 // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
2532 // It's perfectly okay when the object is not an active physical body though.
2533 // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
2534 // but only if the object is not physial and active. This is important for rotating doors.
2535 // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
2536 // scene
2537 PhysicsActor pa = part.PhysActor; 2770 PhysicsActor pa = part.PhysActor;
2538 2771
2539 if (pa != null && !pa.IsPhysical) 2772 // keep using physactor ideia of isphysical
2773 // it should be SOP ideia of that
2774 // not much of a issue with ubOde
2775 if (pa != null && pa.IsPhysical)
2776 isphys = true;
2777 else
2778 isphys = false;
2779
2780 // SL doesn't let scripts rotate root of physical linksets
2781 if (isroot && isphys)
2782 return;
2783
2784 part.UpdateRotation(rot);
2785
2786 // Update rotation does not move the object in the physics engine if it's a non physical linkset
2787 // so do a nasty update of parts positions if is a root part rotation
2788 if (isroot && pa != null) // with if above implies non physical root part
2540 { 2789 {
2541 part.ParentGroup.ResetChildPrimPhysicsPositions(); 2790 part.ParentGroup.ResetChildPrimPhysicsPositions();
2542 } 2791 }
2792 else // fix sitting avatars. This is only needed bc of how we link avas to child parts, not root part
2793 {
2794 // List<ScenePresence> sittingavas = part.ParentGroup.GetLinkedAvatars();
2795 List<ScenePresence> sittingavas = part.ParentGroup.GetSittingAvatars();
2796 if (sittingavas.Count > 0)
2797 {
2798 foreach (ScenePresence av in sittingavas)
2799 {
2800 if (isroot || part.LocalId == av.ParentID)
2801 av.SendTerseUpdateToAllClients();
2802 }
2803 }
2804 }
2543 } 2805 }
2544 2806
2545 /// <summary> 2807 /// <summary>
@@ -2556,6 +2818,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2556 2818
2557 m_host.AddScriptLPS(1); 2819 m_host.AddScriptLPS(1);
2558 Quaternion q = m_host.GetWorldRotation(); 2820 Quaternion q = m_host.GetWorldRotation();
2821
2822 if (m_host.ParentGroup != null && m_host.ParentGroup.AttachmentPoint != 0)
2823 {
2824 ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2825 if (avatar != null)
2826 {
2827 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2828 q = avatar.CameraRotation * q; // Mouselook
2829 else
2830 q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2831 }
2832 }
2833
2559 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2834 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2560 } 2835 }
2561 2836
@@ -2583,14 +2858,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2583 return new LSL_Rotation(q); 2858 return new LSL_Rotation(q);
2584 } 2859 }
2585 2860
2586 return new LSL_Rotation(part.GetWorldRotation()); 2861 q = part.GetWorldRotation();
2862 if (part.ParentGroup.AttachmentPoint != 0)
2863 {
2864 ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
2865 if (avatar != null)
2866 {
2867 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2868 q = avatar.CameraRotation * q; // Mouselook
2869 else
2870 q = avatar.Rotation * q; // Currently infrequently updated so may be inaccurate
2871 }
2872 }
2873
2874 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2587 } 2875 }
2588 2876
2589 public LSL_Rotation llGetLocalRot() 2877 public LSL_Rotation llGetLocalRot()
2590 { 2878 {
2591 m_host.AddScriptLPS(1); 2879 return GetPartLocalRot(m_host);
2880 }
2592 2881
2593 return new LSL_Rotation(m_host.RotationOffset); 2882 private LSL_Rotation GetPartLocalRot(SceneObjectPart part)
2883 {
2884 m_host.AddScriptLPS(1);
2885 Quaternion rot = part.RotationOffset;
2886 return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
2594 } 2887 }
2595 2888
2596 public void llSetForce(LSL_Vector force, int local) 2889 public void llSetForce(LSL_Vector force, int local)
@@ -2620,32 +2913,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2620 return force; 2913 return force;
2621 } 2914 }
2622 2915
2623 public void llSetVelocity(LSL_Vector velocity, int local) 2916 public void llSetVelocity(LSL_Vector vel, int local)
2624 { 2917 {
2625 m_host.AddScriptLPS(1); 2918 m_host.AddScriptLPS(1);
2626 2919 m_host.SetVelocity(new Vector3((float)vel.x, (float)vel.y, (float)vel.z), local != 0);
2627 if (!m_host.ParentGroup.IsDeleted)
2628 {
2629 if (local != 0)
2630 velocity *= llGetRot();
2631
2632 m_host.ParentGroup.RootPart.Velocity = velocity;
2633 }
2634 } 2920 }
2635 2921
2636 public void llSetAngularVelocity(LSL_Vector angularVelocity, int local) 2922 public void llSetAngularVelocity(LSL_Vector avel, int local)
2637 { 2923 {
2638 m_host.AddScriptLPS(1); 2924 m_host.AddScriptLPS(1);
2639 2925 m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0);
2640 if (!m_host.ParentGroup.IsDeleted)
2641 {
2642 if (local != 0)
2643 angularVelocity *= llGetRot();
2644
2645 m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity;
2646 }
2647 } 2926 }
2648
2649 public LSL_Integer llTarget(LSL_Vector position, double range) 2927 public LSL_Integer llTarget(LSL_Vector position, double range)
2650 { 2928 {
2651 m_host.AddScriptLPS(1); 2929 m_host.AddScriptLPS(1);
@@ -2696,16 +2974,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2696 m_host.ApplyImpulse(v, local != 0); 2974 m_host.ApplyImpulse(v, local != 0);
2697 } 2975 }
2698 2976
2977
2699 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2978 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2700 { 2979 {
2701 m_host.AddScriptLPS(1); 2980 m_host.AddScriptLPS(1);
2702 m_host.ApplyAngularImpulse(force, local != 0); 2981 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2703 } 2982 }
2704 2983
2705 public void llSetTorque(LSL_Vector torque, int local) 2984 public void llSetTorque(LSL_Vector torque, int local)
2706 { 2985 {
2707 m_host.AddScriptLPS(1); 2986 m_host.AddScriptLPS(1);
2708 m_host.SetAngularImpulse(torque, local != 0); 2987 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2709 } 2988 }
2710 2989
2711 public LSL_Vector llGetTorque() 2990 public LSL_Vector llGetTorque()
@@ -2722,20 +3001,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2722 llSetTorque(torque, local); 3001 llSetTorque(torque, local);
2723 } 3002 }
2724 3003
3004
2725 public LSL_Vector llGetVel() 3005 public LSL_Vector llGetVel()
2726 { 3006 {
2727 m_host.AddScriptLPS(1); 3007 m_host.AddScriptLPS(1);
2728 3008
2729 Vector3 vel; 3009 Vector3 vel = Vector3.Zero;
2730 3010
2731 if (m_host.ParentGroup.IsAttachment) 3011 if (m_host.ParentGroup.IsAttachment)
2732 { 3012 {
2733 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 3013 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2734 vel = avatar.GetWorldVelocity(); 3014 if (avatar != null)
3015 vel = avatar.GetWorldVelocity();
2735 } 3016 }
2736 else 3017 else
2737 { 3018 {
2738 vel = m_host.Velocity; 3019 vel = m_host.ParentGroup.RootPart.Velocity;
2739 } 3020 }
2740 3021
2741 return new LSL_Vector(vel); 3022 return new LSL_Vector(vel);
@@ -2751,8 +3032,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2751 public LSL_Vector llGetOmega() 3032 public LSL_Vector llGetOmega()
2752 { 3033 {
2753 m_host.AddScriptLPS(1); 3034 m_host.AddScriptLPS(1);
2754 3035 Vector3 avel = m_host.AngularVelocity;
2755 return new LSL_Vector(m_host.AngularVelocity); 3036 return new LSL_Vector(avel.X, avel.Y, avel.Z);
2756 } 3037 }
2757 3038
2758 public LSL_Float llGetTimeOfDay() 3039 public LSL_Float llGetTimeOfDay()
@@ -2806,7 +3087,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2806 m_SoundModule.SendSound( 3087 m_SoundModule.SendSound(
2807 m_host.UUID, 3088 m_host.UUID,
2808 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), 3089 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
2809 volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None, 3090 volume, false, 0,
2810 0, false, false); 3091 0, false, false);
2811 } 3092 }
2812 } 3093 }
@@ -2817,7 +3098,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2817 if (m_SoundModule != null) 3098 if (m_SoundModule != null)
2818 { 3099 {
2819 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 3100 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2820 volume, 20, false); 3101 volume, 20, false,false);
2821 } 3102 }
2822 } 3103 }
2823 3104
@@ -2827,16 +3108,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2827 if (m_SoundModule != null) 3108 if (m_SoundModule != null)
2828 { 3109 {
2829 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 3110 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2830 volume, 20, true); 3111 volume, 20, true, false);
2831 } 3112 }
2832 } 3113 }
2833 3114
2834 public void llLoopSoundSlave(string sound, double volume) 3115 public void llLoopSoundSlave(string sound, double volume)
2835 { 3116 {
2836 m_host.AddScriptLPS(1); 3117 m_host.AddScriptLPS(1);
2837 lock (m_host.ParentGroup.LoopSoundSlavePrims) 3118 if (m_SoundModule != null)
2838 { 3119 {
2839 m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host); 3120 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
3121 volume, 20, false, true);
2840 } 3122 }
2841 } 3123 }
2842 3124
@@ -3111,7 +3393,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3111 return src.ToLower(); 3393 return src.ToLower();
3112 } 3394 }
3113 3395
3114 public void llGiveMoney(string destination, int amount) 3396 public LSL_Integer llGiveMoney(string destination, int amount)
3115 { 3397 {
3116 Util.FireAndForget(x => 3398 Util.FireAndForget(x =>
3117 { 3399 {
@@ -3142,9 +3424,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3142 return; 3424 return;
3143 } 3425 }
3144 3426
3427 string reason;
3145 money.ObjectGiveMoney( 3428 money.ObjectGiveMoney(
3146 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 3429
3430 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount,UUID.Zero, out reason);
3147 }, null, "LSL_Api.llGiveMoney"); 3431 }, null, "LSL_Api.llGiveMoney");
3432
3433 return 0;
3148 } 3434 }
3149 3435
3150 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3436 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
@@ -3177,6 +3463,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3177 3463
3178 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3464 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
3179 { 3465 {
3466 doObjectRez(inventory, pos, vel, rot, param, true);
3467 }
3468
3469 public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot)
3470 {
3180 m_host.AddScriptLPS(1); 3471 m_host.AddScriptLPS(1);
3181 3472
3182 Util.FireAndForget(x => 3473 Util.FireAndForget(x =>
@@ -3203,15 +3494,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3203 return; 3494 return;
3204 } 3495 }
3205 3496
3206 // need the magnitude later 3497 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param, atRoot);
3207 // float velmag = (float)Util.GetMagnitude(llvel);
3208
3209 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
3210 3498
3211 // If either of these are null, then there was an unknown error. 3499 // If either of these are null, then there was an unknown error.
3212 if (new_groups == null) 3500 if (new_groups == null)
3213 return; 3501 return;
3214 3502
3503 bool notAttachment = !m_host.ParentGroup.IsAttachment;
3504
3215 foreach (SceneObjectGroup group in new_groups) 3505 foreach (SceneObjectGroup group in new_groups)
3216 { 3506 {
3217 // objects rezzed with this method are die_at_edge by default. 3507 // objects rezzed with this method are die_at_edge by default.
@@ -3225,21 +3515,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3225 group.RootPart.UUID.ToString()) }, 3515 group.RootPart.UUID.ToString()) },
3226 new DetectParams[0])); 3516 new DetectParams[0]));
3227 3517
3228 float groupmass = group.GetMass(); 3518 if (notAttachment)
3519 {
3520 float groupmass = group.GetMass();
3229 3521
3230 PhysicsActor pa = group.RootPart.PhysActor; 3522 PhysicsActor pa = group.RootPart.PhysActor;
3231 3523
3232 //Recoil. 3524 //Recoil.
3233 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3525 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3234 {
3235 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3236 if (recoil != Vector3.Zero)
3237 { 3526 {
3238 llApplyImpulse(recoil, 0); 3527 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3528 if (recoil != Vector3.Zero)
3529 {
3530 llApplyImpulse(recoil, 0);
3531 }
3239 } 3532 }
3240 } 3533 }
3241 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3534 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3242 } 3535 }
3536
3243 }, null, "LSL_Api.llRezAtRoot"); 3537 }, null, "LSL_Api.llRezAtRoot");
3244 3538
3245 //ScriptSleep((int)((groupmass * velmag) / 10)); 3539 //ScriptSleep((int)((groupmass * velmag) / 10));
@@ -3248,38 +3542,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3248 3542
3249 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3543 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
3250 { 3544 {
3251 llRezAtRoot(inventory, pos, vel, rot, param); 3545 doObjectRez(inventory, pos, vel, rot, param, false);
3252 } 3546 }
3253 3547
3254 public void llLookAt(LSL_Vector target, double strength, double damping) 3548 public void llLookAt(LSL_Vector target, double strength, double damping)
3255 { 3549 {
3256 m_host.AddScriptLPS(1); 3550 m_host.AddScriptLPS(1);
3257 // Determine where we are looking from
3258 LSL_Vector from = llGetPos();
3259 3551
3260 // normalized direction to target 3552 // Get the normalized vector to the target
3261 LSL_Vector dir = llVecNorm(target - from); 3553 LSL_Vector d1 = llVecNorm(target - llGetPos());
3262 // use vertical to help compute left axis
3263 LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
3264 // find normalized left axis parallel to horizon
3265 LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
3266 // make up orthogonal to left and dir
3267 up = LSL_Vector.Cross(dir, left);
3268 3554
3269 // compute rotation based on orthogonal axes 3555 // Get the bearing (yaw)
3270 LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up); 3556 LSL_Vector a1 = new LSL_Vector(0,0,0);
3557 a1.z = llAtan2(d1.y, d1.x);
3271 3558
3272 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 3559 // Get the elevation (pitch)
3273 // set the rotation of the object, copy that behavior 3560 LSL_Vector a2 = new LSL_Vector(0,0,0);
3274 PhysicsActor pa = m_host.PhysActor; 3561 a2.y= -llAtan2(d1.z, llSqrt((d1.x * d1.x) + (d1.y * d1.y)));
3275 3562
3276 if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical) 3563 LSL_Rotation r1 = llEuler2Rot(a1);
3564 LSL_Rotation r2 = llEuler2Rot(a2);
3565 LSL_Rotation r3 = new LSL_Rotation(0.000000, 0.707107, 0.000000, 0.707107);
3566
3567 if (m_host.PhysActor == null || !m_host.PhysActor.IsPhysical)
3277 { 3568 {
3278 llSetRot(rot); 3569 // Do nothing if either value is 0 (this has been checked in SL)
3570 if (strength <= 0.0 || damping <= 0.0)
3571 return;
3572
3573 llSetRot(r3 * r2 * r1);
3279 } 3574 }
3280 else 3575 else
3281 { 3576 {
3282 m_host.StartLookAt(rot, (float)strength, (float)damping); 3577 if (strength == 0)
3578 {
3579 llSetRot(r3 * r2 * r1);
3580 return;
3581 }
3582
3583 m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping);
3283 } 3584 }
3284 } 3585 }
3285 3586
@@ -3325,22 +3626,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3325 } 3626 }
3326 else 3627 else
3327 { 3628 {
3328 if (m_host.IsRoot) 3629 // new SL always returns object mass
3329 { 3630// if (m_host.IsRoot)
3631// {
3330 return m_host.ParentGroup.GetMass(); 3632 return m_host.ParentGroup.GetMass();
3331 } 3633// }
3332 else 3634// else
3333 { 3635// {
3334 return m_host.GetMass(); 3636// return m_host.GetMass();
3335 } 3637// }
3336 } 3638 }
3337 } 3639 }
3338 3640
3339 public LSL_Float llGetMassMKS() 3641 public LSL_Float llGetMassMKS()
3340 { 3642 {
3341 // this is what the wiki says it does! 3643 return 100f * llGetMass();
3342 // http://wiki.secondlife.com/wiki/LlGetMassMKS
3343 return llGetMass() * 100.0;
3344 } 3644 }
3345 3645
3346 public void llCollisionFilter(string name, string id, int accept) 3646 public void llCollisionFilter(string name, string id, int accept)
@@ -3390,7 +3690,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3390 { 3690 {
3391 // Unregister controls from Presence 3691 // Unregister controls from Presence
3392 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); 3692 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
3393 // Remove Take Control permission. 3693 // Remove Take Control permission.
3394 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3694 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3395 } 3695 }
3396 } 3696 }
@@ -3419,7 +3719,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3419 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3719 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3420 3720
3421 if (attachmentsModule != null) 3721 if (attachmentsModule != null)
3422 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true); 3722 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false, true);
3423 else 3723 else
3424 return false; 3724 return false;
3425 } 3725 }
@@ -3449,9 +3749,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3449 { 3749 {
3450 m_host.AddScriptLPS(1); 3750 m_host.AddScriptLPS(1);
3451 3751
3452// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3453// return;
3454
3455 if (m_item.PermsGranter != m_host.OwnerID) 3752 if (m_item.PermsGranter != m_host.OwnerID)
3456 return; 3753 return;
3457 3754
@@ -3495,7 +3792,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3495 public void llInstantMessage(string user, string message) 3792 public void llInstantMessage(string user, string message)
3496 { 3793 {
3497 m_host.AddScriptLPS(1); 3794 m_host.AddScriptLPS(1);
3498 3795 UUID result;
3796 if (!UUID.TryParse(user, out result) || result == UUID.Zero)
3797 {
3798 Error("llInstantMessage","An invalid key was passed to llInstantMessage");
3799 ScriptSleep(2000);
3800 return;
3801 }
3802
3499 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3803 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
3500 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, 3804 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
3501 // but I don't think we have a list of scenes available from here. 3805 // but I don't think we have a list of scenes available from here.
@@ -3505,31 +3809,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3505 3809
3506 // TODO: figure out values for client, fromSession, and imSessionID 3810 // TODO: figure out values for client, fromSession, and imSessionID
3507 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); 3811 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
3812 UUID friendTransactionID = UUID.Random();
3508 3813
3814 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3815
3509 GridInstantMessage msg = new GridInstantMessage(); 3816 GridInstantMessage msg = new GridInstantMessage();
3510 msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid; 3817 msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid;
3511 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3818 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3512 msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here 3819 msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here
3513// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3820 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
3514// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3821 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
3515 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3822
3516 //if (client != null)
3517 //{
3518 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
3519 //}
3520 //else
3521 //{
3522 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
3523 //}
3524 // Cap the message length at 1024.
3525 if (message != null && message.Length > 1024) 3823 if (message != null && message.Length > 1024)
3526 msg.message = message.Substring(0, 1024); 3824 msg.message = message.Substring(0, 1024);
3527 else 3825 else
3528 msg.message = message; 3826 msg.message = message;
3529 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3827 msg.dialog = (byte)19; // MessageFromObject
3530 msg.fromGroup = false;// fromGroup; 3828 msg.fromGroup = false;// fromGroup;
3531 msg.offline = (byte)0; //offline; 3829 msg.offline = (byte)0; //offline;
3532 msg.ParentEstateID = 0; //ParentEstateID; 3830 msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID;
3533 msg.Position = new Vector3(m_host.AbsolutePosition); 3831 msg.Position = new Vector3(m_host.AbsolutePosition);
3534 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3832 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
3535 3833
@@ -3648,25 +3946,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3648 { 3946 {
3649 m_host.AddScriptLPS(1); 3947 m_host.AddScriptLPS(1);
3650 3948
3651 if (m_host.PhysActor != null) 3949 PIDHoverType hoverType = PIDHoverType.Ground;
3950 if (water != 0)
3652 { 3951 {
3653 PIDHoverType hoverType = PIDHoverType.Ground; 3952 hoverType = PIDHoverType.GroundAndWater;
3654 if (water != 0)
3655 {
3656 hoverType = PIDHoverType.GroundAndWater;
3657 }
3658
3659 m_host.SetHoverHeight((float)height, hoverType, (float)tau);
3660 } 3953 }
3954 m_host.SetHoverHeight((float)height, hoverType, (float)tau);
3661 } 3955 }
3662 3956
3663 public void llStopHover() 3957 public void llStopHover()
3664 { 3958 {
3665 m_host.AddScriptLPS(1); 3959 m_host.AddScriptLPS(1);
3666 if (m_host.PhysActor != null) 3960 m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
3667 {
3668 m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
3669 }
3670 } 3961 }
3671 3962
3672 public void llMinEventDelay(double delay) 3963 public void llMinEventDelay(double delay)
@@ -3832,7 +4123,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3832 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 4123 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3833 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 4124 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3834 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 4125 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3835 ScriptBaseClass.PERMISSION_ATTACH; 4126 ScriptBaseClass.PERMISSION_ATTACH |
4127 ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS;
3836 } 4128 }
3837 else 4129 else
3838 { 4130 {
@@ -3849,15 +4141,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3849 if (World.GetExtraSetting("auto_grant_attach_perms") == "true") 4141 if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
3850 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH; 4142 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
3851 } 4143 }
4144 if (World.GetExtraSetting("auto_grant_all_perms") == "true")
4145 {
4146 implicitPerms = perm;
4147 }
3852 } 4148 }
3853 4149
3854 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 4150 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3855 { 4151 {
3856 lock (m_host.TaskInventory) 4152 m_host.TaskInventory.LockItemsForWrite(true);
3857 { 4153 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3858 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 4154 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3859 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 4155 m_host.TaskInventory.LockItemsForWrite(false);
3860 }
3861 4156
3862 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 4157 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3863 "run_time_permissions", new Object[] { 4158 "run_time_permissions", new Object[] {
@@ -3901,11 +4196,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3901 4196
3902 if (!m_waitingForScriptAnswer) 4197 if (!m_waitingForScriptAnswer)
3903 { 4198 {
3904 lock (m_host.TaskInventory) 4199 m_host.TaskInventory.LockItemsForWrite(true);
3905 { 4200 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3906 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 4201 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3907 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 4202 m_host.TaskInventory.LockItemsForWrite(false);
3908 }
3909 4203
3910 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 4204 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3911 m_waitingForScriptAnswer=true; 4205 m_waitingForScriptAnswer=true;
@@ -3934,14 +4228,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3934 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 4228 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3935 llReleaseControls(); 4229 llReleaseControls();
3936 4230
3937 lock (m_host.TaskInventory) 4231 m_host.TaskInventory.LockItemsForWrite(true);
3938 { 4232 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3939 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 4233 m_host.TaskInventory.LockItemsForWrite(false);
3940 } 4234
3941 4235 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3942 m_ScriptEngine.PostScriptEvent( 4236 "run_time_permissions", new Object[] {
3943 m_item.ItemID, 4237 new LSL_Integer(answer) },
3944 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 4238 new DetectParams[0]));
3945 } 4239 }
3946 4240
3947 public LSL_String llGetPermissionsKey() 4241 public LSL_String llGetPermissionsKey()
@@ -3980,15 +4274,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3980 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 4274 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
3981 { 4275 {
3982 List<SceneObjectPart> parts = GetLinkParts(linknumber); 4276 List<SceneObjectPart> parts = GetLinkParts(linknumber);
3983 4277 if (parts.Count > 0)
3984 foreach (SceneObjectPart part in parts) 4278 {
3985 part.SetFaceColorAlpha(face, color, null); 4279 try
4280 {
4281 foreach (SceneObjectPart part in parts)
4282 part.SetFaceColorAlpha(face, color, null);
4283 }
4284 finally { }
4285 }
3986 } 4286 }
3987 4287
3988 public void llCreateLink(string target, int parent) 4288 public void llCreateLink(string target, int parent)
3989 { 4289 {
3990 m_host.AddScriptLPS(1); 4290 m_host.AddScriptLPS(1);
3991 4291
4292 UUID targetID;
4293
4294 if (!UUID.TryParse(target, out targetID))
4295 return;
4296
3992 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4297 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3993 && !m_automaticLinkPermission) 4298 && !m_automaticLinkPermission)
3994 { 4299 {
@@ -4104,10 +4409,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4104 // Restructuring Multiple Prims. 4409 // Restructuring Multiple Prims.
4105 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4410 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
4106 parts.Remove(parentPrim.RootPart); 4411 parts.Remove(parentPrim.RootPart);
4107 foreach (SceneObjectPart part in parts) 4412 if (parts.Count > 0)
4108 { 4413 {
4109 parentPrim.DelinkFromGroup(part.LocalId, true); 4414 try
4110 } 4415 {
4416 foreach (SceneObjectPart part in parts)
4417 {
4418 parentPrim.DelinkFromGroup(part.LocalId, true);
4419 }
4420 }
4421 finally { }
4422 }
4423
4111 parentPrim.HasGroupChanged = true; 4424 parentPrim.HasGroupChanged = true;
4112 parentPrim.ScheduleGroupForFullUpdate(); 4425 parentPrim.ScheduleGroupForFullUpdate();
4113 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4426 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
@@ -4116,12 +4429,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4116 { 4429 {
4117 SceneObjectPart newRoot = parts[0]; 4430 SceneObjectPart newRoot = parts[0];
4118 parts.Remove(newRoot); 4431 parts.Remove(newRoot);
4119 foreach (SceneObjectPart part in parts) 4432
4433 try
4120 { 4434 {
4121 // Required for linking 4435 foreach (SceneObjectPart part in parts)
4122 part.ClearUpdateSchedule(); 4436 {
4123 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4437 part.ClearUpdateSchedule();
4438 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4439 }
4124 } 4440 }
4441 finally { }
4442
4125 newRoot.ParentGroup.HasGroupChanged = true; 4443 newRoot.ParentGroup.HasGroupChanged = true;
4126 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4444 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
4127 } 4445 }
@@ -4142,13 +4460,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4142 { 4460 {
4143 m_host.AddScriptLPS(1); 4461 m_host.AddScriptLPS(1);
4144 4462
4145 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4463 TaskInventoryItem item = m_item;
4464
4465 if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4146 && !m_automaticLinkPermission) 4466 && !m_automaticLinkPermission)
4147 { 4467 {
4148 Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set"); 4468 Error("llBreakAllLinks","Script trying to link but PERMISSION_CHANGE_LINKS permission not set!");
4149 return; 4469 return;
4150 } 4470 }
4151
4152 BreakAllLinks(); 4471 BreakAllLinks();
4153 } 4472 }
4154 4473
@@ -4173,13 +4492,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4173 public LSL_String llGetLinkKey(int linknum) 4492 public LSL_String llGetLinkKey(int linknum)
4174 { 4493 {
4175 m_host.AddScriptLPS(1); 4494 m_host.AddScriptLPS(1);
4495 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
4496 if (part != null)
4497 {
4498 return part.UUID.ToString();
4499 }
4500 else
4501 {
4502 if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1))
4503 {
4504 linknum -= (m_host.ParentGroup.PrimCount) + 1;
4176 4505
4177 ISceneEntity entity = GetLinkEntity(m_host, linknum); 4506 if (linknum < 0)
4507 return UUID.Zero.ToString();
4178 4508
4179 if (entity != null) 4509 List<ScenePresence> avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET);
4180 return entity.UUID.ToString(); 4510 if (avatars.Count > linknum)
4181 else 4511 {
4182 return ScriptBaseClass.NULL_KEY; 4512 return avatars[linknum].UUID.ToString();
4513 }
4514 }
4515 return UUID.Zero.ToString();
4516 }
4183 } 4517 }
4184 4518
4185 /// <summary> 4519 /// <summary>
@@ -4238,17 +4572,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4238 m_host.AddScriptLPS(1); 4572 m_host.AddScriptLPS(1);
4239 int count = 0; 4573 int count = 0;
4240 4574
4241 lock (m_host.TaskInventory) 4575 m_host.TaskInventory.LockItemsForRead(true);
4576 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4242 { 4577 {
4243 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4578 if (inv.Value.Type == type || type == -1)
4244 { 4579 {
4245 if (inv.Value.Type == type || type == -1) 4580 count = count + 1;
4246 {
4247 count = count + 1;
4248 }
4249 } 4581 }
4250 } 4582 }
4251 4583
4584 m_host.TaskInventory.LockItemsForRead(false);
4252 return count; 4585 return count;
4253 } 4586 }
4254 4587
@@ -4257,16 +4590,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4257 m_host.AddScriptLPS(1); 4590 m_host.AddScriptLPS(1);
4258 ArrayList keys = new ArrayList(); 4591 ArrayList keys = new ArrayList();
4259 4592
4260 lock (m_host.TaskInventory) 4593 m_host.TaskInventory.LockItemsForRead(true);
4594 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4261 { 4595 {
4262 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4596 if (inv.Value.Type == type || type == -1)
4263 { 4597 {
4264 if (inv.Value.Type == type || type == -1) 4598 keys.Add(inv.Value.Name);
4265 {
4266 keys.Add(inv.Value.Name);
4267 }
4268 } 4599 }
4269 } 4600 }
4601 m_host.TaskInventory.LockItemsForRead(false);
4270 4602
4271 if (keys.Count == 0) 4603 if (keys.Count == 0)
4272 { 4604 {
@@ -4336,6 +4668,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4336 } 4668 }
4337 } 4669 }
4338 } 4670 }
4671
4339 // destination is an avatar 4672 // destination is an avatar
4340 string message; 4673 string message;
4341 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message); 4674 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message);
@@ -4346,27 +4679,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4346 return; 4679 return;
4347 } 4680 }
4348 4681
4349 if (m_TransferModule != null) 4682 byte[] bucket = new byte[1];
4350 { 4683 bucket[0] = (byte)item.Type;
4351 byte[] bucket = new byte[1]; 4684 //byte[] objBytes = agentItem.ID.GetBytes();
4352 bucket[0] = (byte)item.Type; 4685 //Array.Copy(objBytes, 0, bucket, 1, 16);
4353 4686
4354 GridInstantMessage msg = new GridInstantMessage(World, 4687 GridInstantMessage msg = new GridInstantMessage(World,
4355 m_host.OwnerID, m_host.Name, destId, 4688 m_host.OwnerID, m_host.Name, destId,
4356 (byte)InstantMessageDialog.TaskInventoryOffered, 4689 (byte)InstantMessageDialog.TaskInventoryOffered,
4357 false, item.Name+". "+m_host.Name+" is located at "+ 4690 false, item.Name+". "+m_host.Name+" is located at "+
4358 World.RegionInfo.RegionName+" "+ 4691 World.RegionInfo.RegionName+" "+
4359 m_host.AbsolutePosition.ToString(), 4692 m_host.AbsolutePosition.ToString(),
4360 agentItem.ID, true, m_host.AbsolutePosition, 4693 agentItem.ID, true, m_host.AbsolutePosition,
4361 bucket, true); 4694 bucket, true);
4362 4695
4363 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4696 ScenePresence sp;
4364 }
4365 4697
4698 if (World.TryGetScenePresence(destId, out sp))
4699 {
4700 sp.ControllingClient.SendInstantMessage(msg);
4701 }
4702 else
4703 {
4704 if (m_TransferModule != null)
4705 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4706 }
4707
4708 //This delay should only occur when giving inventory to avatars.
4366 ScriptSleep(m_sleepMsOnGiveInventory); 4709 ScriptSleep(m_sleepMsOnGiveInventory);
4367 } 4710 }
4368 } 4711 }
4369 4712
4713 [DebuggerNonUserCode]
4370 public void llRemoveInventory(string name) 4714 public void llRemoveInventory(string name)
4371 { 4715 {
4372 m_host.AddScriptLPS(1); 4716 m_host.AddScriptLPS(1);
@@ -4421,14 +4765,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4421 { 4765 {
4422 m_host.AddScriptLPS(1); 4766 m_host.AddScriptLPS(1);
4423 4767
4424 UUID uuid = (UUID)id; 4768 UUID uuid;
4425 PresenceInfo pinfo = null; 4769 if (UUID.TryParse(id, out uuid))
4426 UserAccount account;
4427
4428 UserInfoCacheEntry ce;
4429
4430 lock (m_userInfoCache)
4431 { 4770 {
4771 PresenceInfo pinfo = null;
4772 UserAccount account;
4773
4774 UserInfoCacheEntry ce;
4432 if (!m_userInfoCache.TryGetValue(uuid, out ce)) 4775 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4433 { 4776 {
4434 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4777 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
@@ -4454,7 +4797,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4454 ce.time = Util.EnvironmentTickCount(); 4797 ce.time = Util.EnvironmentTickCount();
4455 ce.account = account; 4798 ce.account = account;
4456 ce.pinfo = pinfo; 4799 ce.pinfo = pinfo;
4457
4458 m_userInfoCache[uuid] = ce; 4800 m_userInfoCache[uuid] = ce;
4459 } 4801 }
4460 else 4802 else
@@ -4463,78 +4805,77 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4463 return UUID.Zero.ToString(); 4805 return UUID.Zero.ToString();
4464 4806
4465 account = ce.account; 4807 account = ce.account;
4808 pinfo = ce.pinfo;
4809 }
4466 4810
4467 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) 4811 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000)
4468 >= LlRequestAgentDataCacheTimeoutMs) 4812 {
4813 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4814 if (pinfos != null && pinfos.Length > 0)
4469 { 4815 {
4470 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4816 foreach (PresenceInfo p in pinfos)
4471 if (pinfos != null && pinfos.Length > 0)
4472 { 4817 {
4473 foreach (PresenceInfo p in pinfos) 4818 if (p.RegionID != UUID.Zero)
4474 { 4819 {
4475 if (p.RegionID != UUID.Zero) 4820 pinfo = p;
4476 {
4477 pinfo = p;
4478 }
4479 } 4821 }
4480 } 4822 }
4481 else
4482 {
4483 pinfo = null;
4484 }
4485
4486 ce.time = Util.EnvironmentTickCount();
4487 ce.pinfo = pinfo;
4488 } 4823 }
4489 else 4824 else
4490 { 4825 pinfo = null;
4491 pinfo = ce.pinfo; 4826
4492 } 4827 ce.time = Util.EnvironmentTickCount();
4828 ce.pinfo = pinfo;
4493 } 4829 }
4494 }
4495 4830
4496 string reply = String.Empty; 4831 string reply = String.Empty;
4497 4832
4498 switch (data) 4833 switch (data)
4499 { 4834 {
4500 case ScriptBaseClass.DATA_ONLINE: 4835 case ScriptBaseClass.DATA_ONLINE: // DATA_ONLINE (0|1)
4501 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4836 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4502 reply = "1"; 4837 reply = "1";
4503 else 4838 else
4504 reply = "0"; 4839 reply = "0";
4505 break; 4840 break;
4506 case ScriptBaseClass.DATA_NAME: // (First Last) 4841 case ScriptBaseClass.DATA_NAME: // DATA_NAME (First Last)
4507 reply = account.FirstName + " " + account.LastName; 4842 reply = account.FirstName + " " + account.LastName;
4508 break; 4843 break;
4509 case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD) 4844 case ScriptBaseClass.DATA_BORN: // DATA_BORN (YYYY-MM-DD)
4510 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4845 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4511 born = born.AddSeconds(account.Created); 4846 born = born.AddSeconds(account.Created);
4512 reply = born.ToString("yyyy-MM-dd"); 4847 reply = born.ToString("yyyy-MM-dd");
4513 break; 4848 break;
4514 case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0) 4849 case ScriptBaseClass.DATA_RATING: // DATA_RATING (0,0,0,0,0,0)
4515 reply = "0,0,0,0,0,0"; 4850 reply = "0,0,0,0,0,0";
4516 break; 4851 break;
4517 case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant. 4852 case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant.
4518 reply = account.UserLevel.ToString(); 4853 reply = account.UserLevel.ToString();
4519 break; 4854 break;
4520 case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3) 4855 case ScriptBaseClass.DATA_PAYINFO: // DATA_PAYINFO (0|1|2|3)
4521 reply = "0"; 4856 reply = "0";
4522 break; 4857 break;
4523 default: 4858 default:
4524 return UUID.Zero.ToString(); // Raise no event 4859 return UUID.Zero.ToString(); // Raise no event
4525 } 4860 }
4526 4861
4527 UUID rq = UUID.Random(); 4862 UUID rq = UUID.Random();
4528 4863
4529 UUID tid = AsyncCommands. 4864 UUID tid = AsyncCommands.
4530 DataserverPlugin.RegisterRequest(m_host.LocalId, 4865 DataserverPlugin.RegisterRequest(m_host.LocalId,
4531 m_item.ItemID, rq.ToString()); 4866 m_item.ItemID, rq.ToString());
4532 4867
4533 AsyncCommands. 4868 AsyncCommands.
4534 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4869 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4535 4870
4536 ScriptSleep(m_sleepMsOnRequestAgentData); 4871 ScriptSleep(m_sleepMsOnRequestAgentData);
4537 return tid.ToString(); 4872 return tid.ToString();
4873 }
4874 else
4875 {
4876 Error("llRequestAgentData","Invalid UUID passed to llRequestAgentData.");
4877 }
4878 return "";
4538 } 4879 }
4539 4880
4540 public LSL_String llRequestInventoryData(string name) 4881 public LSL_String llRequestInventoryData(string name)
@@ -4588,12 +4929,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4588 if (UUID.TryParse(agent, out agentId)) 4929 if (UUID.TryParse(agent, out agentId))
4589 { 4930 {
4590 ScenePresence presence = World.GetScenePresence(agentId); 4931 ScenePresence presence = World.GetScenePresence(agentId);
4591 if (presence != null) 4932 if (presence != null && presence.PresenceType != PresenceType.Npc)
4592 { 4933 {
4934 // agent must not be a god
4935 if (presence.UserLevel >= 200) return;
4936
4593 // agent must be over the owners land 4937 // agent must be over the owners land
4594 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 4938 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4595 { 4939 {
4596 World.TeleportClientHome(agentId, presence.ControllingClient); 4940 if (!World.TeleportClientHome(agentId, presence.ControllingClient))
4941 {
4942 // They can't be teleported home for some reason
4943 GridRegion regionInfo = World.GridService.GetRegionByUUID(UUID.Zero, new UUID("2b02daac-e298-42fa-9a75-f488d37896e6"));
4944 if (regionInfo != null)
4945 {
4946 World.RequestTeleportLocation(
4947 presence.ControllingClient, regionInfo.RegionHandle, new Vector3(128, 128, 23), Vector3.Zero,
4948 (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome));
4949 }
4950 }
4597 } 4951 }
4598 } 4952 }
4599 } 4953 }
@@ -4611,20 +4965,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4611 ScenePresence presence = World.GetScenePresence(agentId); 4965 ScenePresence presence = World.GetScenePresence(agentId);
4612 if (presence != null && presence.PresenceType != PresenceType.Npc) 4966 if (presence != null && presence.PresenceType != PresenceType.Npc)
4613 { 4967 {
4614 // agent must not be a god
4615 if (presence.GodLevel >= 200) return;
4616
4617 if (destination == String.Empty) 4968 if (destination == String.Empty)
4618 destination = World.RegionInfo.RegionName; 4969 destination = World.RegionInfo.RegionName;
4619 4970
4620 // agent must be over the owners land 4971 if (m_item.PermsGranter == agentId)
4621 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 4972 {
4973 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0)
4974 {
4975 DoLLTeleport(presence, destination, targetPos, targetLookAt);
4976 }
4977 }
4978
4979 // agent must be wearing the object
4980 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4622 { 4981 {
4623 DoLLTeleport(presence, destination, targetPos, targetLookAt); 4982 DoLLTeleport(presence, destination, targetPos, targetLookAt);
4624 } 4983 }
4625 else // or must be wearing the prim 4984 else
4626 { 4985 {
4627 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) 4986 // agent must not be a god
4987 if (presence.GodLevel >= 200) return;
4988
4989 // agent must be over the owners land
4990 ILandObject agentLand = World.LandChannel.GetLandObject(presence.AbsolutePosition);
4991 ILandObject objectLand = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
4992 if (m_host.OwnerID == objectLand.LandData.OwnerID && m_host.OwnerID == agentLand.LandData.OwnerID)
4628 { 4993 {
4629 DoLLTeleport(presence, destination, targetPos, targetLookAt); 4994 DoLLTeleport(presence, destination, targetPos, targetLookAt);
4630 } 4995 }
@@ -4642,23 +5007,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4642 5007
4643 if (UUID.TryParse(agent, out agentId)) 5008 if (UUID.TryParse(agent, out agentId))
4644 { 5009 {
5010 // This function is owner only!
5011 if (m_host.OwnerID != agentId)
5012 return;
5013
4645 ScenePresence presence = World.GetScenePresence(agentId); 5014 ScenePresence presence = World.GetScenePresence(agentId);
4646 if (presence != null && presence.PresenceType != PresenceType.Npc) 5015
5016 if (presence == null || presence.PresenceType == PresenceType.Npc)
5017 return;
5018
5019 // Can't TP sitting avatars
5020 if (presence.ParentID != 0) // Sitting
5021 return;
5022
5023 if (m_item.PermsGranter == agentId)
4647 { 5024 {
4648 // agent must not be a god 5025 // If attached using llAttachToAvatarTemp, cowardly refuse
4649 if (presence.GodLevel >= 200) return; 5026 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.ParentGroup.FromItemID == UUID.Zero)
5027 return;
4650 5028
4651 // agent must be over the owners land 5029 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0)
4652 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4653 { 5030 {
4654 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); 5031 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4655 }
4656 else // or must be wearing the prim
4657 {
4658 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4659 {
4660 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4661 }
4662 } 5032 }
4663 } 5033 }
4664 } 5034 }
@@ -4707,9 +5077,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4707 { 5077 {
4708 Error("llTextBox", "Empty message"); 5078 Error("llTextBox", "Empty message");
4709 } 5079 }
4710 else if (message.Length > 512) 5080 else if (Encoding.UTF8.GetByteCount(message) > 512)
4711 { 5081 {
4712 Error("llTextBox", "Message more than 512 characters"); 5082 Error("llTextBox", "Message longer than 512 bytes");
4713 } 5083 }
4714 else 5084 else
4715 { 5085 {
@@ -4732,9 +5102,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4732 { 5102 {
4733 m_host.AddScriptLPS(1); 5103 m_host.AddScriptLPS(1);
4734 5104
5105 if(impact_sound == "")
5106 {
5107 m_host.CollisionSoundVolume = (float)impact_volume;
5108 m_host.CollisionSound = m_host.invalidCollisionSoundUUID;
5109 m_host.CollisionSoundType = 0;
5110 return;
5111 }
4735 // TODO: Parameter check logic required. 5112 // TODO: Parameter check logic required.
4736 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); 5113 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4737 m_host.CollisionSoundVolume = (float)impact_volume; 5114 m_host.CollisionSoundVolume = (float)impact_volume;
5115 m_host.CollisionSoundType = 1;
4738 } 5116 }
4739 5117
4740 public LSL_String llGetAnimation(string id) 5118 public LSL_String llGetAnimation(string id)
@@ -4748,14 +5126,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4748 5126
4749 if (m_host.RegionHandle == presence.RegionHandle) 5127 if (m_host.RegionHandle == presence.RegionHandle)
4750 { 5128 {
4751 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4752
4753 if (presence != null) 5129 if (presence != null)
4754 { 5130 {
4755 AnimationSet currentAnims = presence.Animator.Animations; 5131// if (presence.SitGround)
4756 string currentAnimationState = String.Empty; 5132// return "Sitting on Ground";
4757 if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) 5133// if (presence.ParentID != 0 || presence.ParentUUID != UUID.Zero)
4758 return currentAnimationState; 5134// return "Sitting";
5135
5136 string movementAnimation = presence.Animator.CurrentMovementAnimation;
5137 string lslMovementAnimation;
5138
5139 if (MovementAnimationsForLSL.TryGetValue(movementAnimation, out lslMovementAnimation))
5140 return lslMovementAnimation;
4759 } 5141 }
4760 } 5142 }
4761 5143
@@ -4903,7 +5285,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4903 { 5285 {
4904 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 5286 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4905 float distance_term = distance * distance * distance; // Script Energy 5287 float distance_term = distance * distance * distance; // Script Energy
4906 float pusher_mass = m_host.GetMass(); 5288 // use total object mass and not part
5289 float pusher_mass = m_host.ParentGroup.GetMass();
4907 5290
4908 float PUSH_ATTENUATION_DISTANCE = 17f; 5291 float PUSH_ATTENUATION_DISTANCE = 17f;
4909 float PUSH_ATTENUATION_SCALE = 5f; 5292 float PUSH_ATTENUATION_SCALE = 5f;
@@ -4938,7 +5321,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4938 { 5321 {
4939 if (local != 0) 5322 if (local != 0)
4940 { 5323 {
4941 applied_linear_impulse *= m_host.GetWorldRotation(); 5324// applied_linear_impulse *= m_host.GetWorldRotation();
5325 applied_linear_impulse *= pusheeav.GetWorldRotation();
4942 } 5326 }
4943 5327
4944 pa.AddForce(applied_linear_impulse, true); 5328 pa.AddForce(applied_linear_impulse, true);
@@ -5292,14 +5676,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5292 { 5676 {
5293 m_host.AddScriptLPS(1); 5677 m_host.AddScriptLPS(1);
5294 5678
5295 if (src == null) 5679 return src.Length;
5296 {
5297 return 0;
5298 }
5299 else
5300 {
5301 return src.Length;
5302 }
5303 } 5680 }
5304 5681
5305 public LSL_Integer llList2Integer(LSL_List src, int index) 5682 public LSL_Integer llList2Integer(LSL_List src, int index)
@@ -5370,7 +5747,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5370 else if (src.Data[index] is LSL_Float) 5747 else if (src.Data[index] is LSL_Float)
5371 return Convert.ToDouble(((LSL_Float)src.Data[index]).value); 5748 return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
5372 else if (src.Data[index] is LSL_String) 5749 else if (src.Data[index] is LSL_String)
5373 return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); 5750 {
5751 string str = ((LSL_String) src.Data[index]).m_string;
5752 Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)");
5753 if (m != Match.Empty)
5754 {
5755 str = m.Value;
5756 double d = 0.0;
5757 if (!Double.TryParse(str, out d))
5758 return 0.0;
5759
5760 return d;
5761 }
5762 return 0.0;
5763 }
5374 return Convert.ToDouble(src.Data[index]); 5764 return Convert.ToDouble(src.Data[index]);
5375 } 5765 }
5376 catch (FormatException) 5766 catch (FormatException)
@@ -5674,7 +6064,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5674 } 6064 }
5675 } 6065 }
5676 } 6066 }
5677 else { 6067 else
6068 {
5678 object[] array = new object[src.Length]; 6069 object[] array = new object[src.Length];
5679 Array.Copy(src.Data, 0, array, 0, src.Length); 6070 Array.Copy(src.Data, 0, array, 0, src.Length);
5680 result = new LSL_List(array); 6071 result = new LSL_List(array);
@@ -5781,7 +6172,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5781 public LSL_Integer llGetRegionAgentCount() 6172 public LSL_Integer llGetRegionAgentCount()
5782 { 6173 {
5783 m_host.AddScriptLPS(1); 6174 m_host.AddScriptLPS(1);
5784 return new LSL_Integer(World.GetRootAgentCount()); 6175
6176 int count = 0;
6177 World.ForEachRootScenePresence(delegate(ScenePresence sp) {
6178 count++;
6179 });
6180
6181 return new LSL_Integer(count);
5785 } 6182 }
5786 6183
5787 public LSL_Vector llGetRegionCorner() 6184 public LSL_Vector llGetRegionCorner()
@@ -5853,6 +6250,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5853 { 6250 {
5854 return ""; 6251 return "";
5855 } 6252 }
6253
5856 } 6254 }
5857 6255
5858 /// <summary> 6256 /// <summary>
@@ -5928,17 +6326,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5928 { 6326 {
5929 for (int i = 0; i < length; i++) 6327 for (int i = 0; i < length; i++)
5930 { 6328 {
6329 int needle = llGetListEntryType(test, 0).value;
6330 int haystack = llGetListEntryType(src, i).value;
6331
5931 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) 6332 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
5932 // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code 6333 // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
5933 // and so the comparison fails even if the LSL_Integer conceptually has the same value. 6334 // and so the comparison fails even if the LSL_Integer conceptually has the same value.
5934 // Therefore, here we test Equals on both the source and destination objects. 6335 // Therefore, here we test Equals on both the source and destination objects.
5935 // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). 6336 // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
5936 if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) 6337 if ((needle == haystack) && (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])))
5937 { 6338 {
5938 int j; 6339 int j;
5939 for (j = 1; j < test.Length; j++) 6340 for (j = 1; j < test.Length; j++)
5940 if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) 6341 {
6342 needle = llGetListEntryType(test, j).value;
6343 haystack = llGetListEntryType(src, i+j).value;
6344
6345 if ((needle != haystack) || (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))))
5941 break; 6346 break;
6347 }
5942 6348
5943 if (j == test.Length) 6349 if (j == test.Length)
5944 { 6350 {
@@ -6087,6 +6493,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6087 flags |= ScriptBaseClass.AGENT_AWAY; 6493 flags |= ScriptBaseClass.AGENT_AWAY;
6088 } 6494 }
6089 6495
6496 UUID busy = new UUID("efcf670c-2d18-8128-973a-034ebc806b67");
6497 UUID[] anims = agent.Animator.GetAnimationArray();
6498 if (Array.Exists<UUID>(anims, a => { return a == busy; }))
6499 {
6500 flags |= ScriptBaseClass.AGENT_BUSY;
6501 }
6502
6090 // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? 6503 // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
6091 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 6504 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
6092 { 6505 {
@@ -6134,6 +6547,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6134 flags |= ScriptBaseClass.AGENT_SITTING; 6547 flags |= ScriptBaseClass.AGENT_SITTING;
6135 } 6548 }
6136 6549
6550 if (agent.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] > 0)
6551 {
6552 flags |= ScriptBaseClass.AGENT_MALE;
6553 }
6554
6137 return flags; 6555 return flags;
6138 } 6556 }
6139 6557
@@ -6288,9 +6706,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6288 6706
6289 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6707 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6290 6708
6291 foreach (SceneObjectPart part in parts) 6709 try
6710 {
6711 foreach (SceneObjectPart part in parts)
6712 {
6713 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6714 }
6715 }
6716 finally
6292 { 6717 {
6293 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6294 } 6718 }
6295 } 6719 }
6296 6720
@@ -6344,13 +6768,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6344 6768
6345 if (m_host.OwnerID == land.LandData.OwnerID) 6769 if (m_host.OwnerID == land.LandData.OwnerID)
6346 { 6770 {
6347 World.TeleportClientHome(agentID, presence.ControllingClient); 6771 Vector3 p = World.GetNearestAllowedPosition(presence, land);
6772 presence.TeleportWithMomentum(p, null);
6773 presence.ControllingClient.SendAlertMessage("You have been ejected from this land");
6348 } 6774 }
6349 } 6775 }
6350 } 6776 }
6351 ScriptSleep(m_sleepMsOnEjectFromLand); 6777 ScriptSleep(m_sleepMsOnEjectFromLand);
6352 } 6778 }
6353 6779
6780 public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers)
6781 {
6782 return ParseString2List(str, separators, in_spacers, false);
6783 }
6784
6354 public LSL_Integer llOverMyLand(string id) 6785 public LSL_Integer llOverMyLand(string id)
6355 { 6786 {
6356 m_host.AddScriptLPS(1); 6787 m_host.AddScriptLPS(1);
@@ -6403,26 +6834,55 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6403 } 6834 }
6404 else 6835 else
6405 { 6836 {
6406 agentSize = GetAgentSize(avatar); 6837// agentSize = new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight);
6838 Vector3 s = avatar.Appearance.AvatarSize;
6839 agentSize = new LSL_Vector(s.X, s.Y, s.Z);
6407 } 6840 }
6408
6409 return agentSize; 6841 return agentSize;
6410 } 6842 }
6411 6843
6412 public LSL_Integer llSameGroup(string agent) 6844 public LSL_Integer llSameGroup(string id)
6413 { 6845 {
6414 m_host.AddScriptLPS(1); 6846 m_host.AddScriptLPS(1);
6415 UUID agentId = new UUID(); 6847 UUID uuid = new UUID();
6416 if (!UUID.TryParse(agent, out agentId)) 6848 if (!UUID.TryParse(id, out uuid))
6417 return new LSL_Integer(0); 6849 return new LSL_Integer(0);
6418 ScenePresence presence = World.GetScenePresence(agentId); 6850
6419 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6851 // Check if it's a group key
6420 return new LSL_Integer(0); 6852 if (uuid == m_host.ParentGroup.RootPart.GroupID)
6421 IClientAPI client = presence.ControllingClient;
6422 if (m_host.GroupID == client.ActiveGroupId)
6423 return new LSL_Integer(1); 6853 return new LSL_Integer(1);
6424 else 6854
6855 // We got passed a UUID.Zero
6856 if (uuid == UUID.Zero)
6857 return new LSL_Integer(0);
6858
6859 // Handle the case where id names an avatar
6860 ScenePresence presence = World.GetScenePresence(uuid);
6861 if (presence != null)
6862 {
6863 if (presence.IsChildAgent)
6864 return new LSL_Integer(0);
6865
6866 IClientAPI client = presence.ControllingClient;
6867 if (m_host.ParentGroup.RootPart.GroupID == client.ActiveGroupId)
6868 return new LSL_Integer(1);
6869
6425 return new LSL_Integer(0); 6870 return new LSL_Integer(0);
6871 }
6872
6873 // Handle object case
6874 SceneObjectPart part = World.GetSceneObjectPart(uuid);
6875 if (part != null)
6876 {
6877 // This will handle both deed and non-deed and also the no
6878 // group case
6879 if (part.ParentGroup.RootPart.GroupID == m_host.ParentGroup.RootPart.GroupID)
6880 return new LSL_Integer(1);
6881
6882 return new LSL_Integer(0);
6883 }
6884
6885 return new LSL_Integer(0);
6426 } 6886 }
6427 6887
6428 public void llUnSit(string id) 6888 public void llUnSit(string id)
@@ -7236,6 +7696,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7236 7696
7237 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) 7697 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
7238 { 7698 {
7699 // LSL quaternions can normalize to 0, normal Quaternions can't.
7700 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
7701 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
7702
7239 part.SitTargetPosition = offset; 7703 part.SitTargetPosition = offset;
7240 part.SitTargetOrientation = rot; 7704 part.SitTargetOrientation = rot;
7241 part.ParentGroup.HasGroupChanged = true; 7705 part.ParentGroup.HasGroupChanged = true;
@@ -7290,7 +7754,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7290 UUID key; 7754 UUID key;
7291 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 7755 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
7292 7756
7293 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 7757 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
7294 { 7758 {
7295 int expires = 0; 7759 int expires = 0;
7296 if (hours != 0) 7760 if (hours != 0)
@@ -7431,29 +7895,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7431 Error("llDialog", "First parameter must be a key"); 7895 Error("llDialog", "First parameter must be a key");
7432 return; 7896 return;
7433 } 7897 }
7434 if (buttons.Length < 1) 7898
7899 int length = buttons.Length;
7900 if (length < 1)
7435 { 7901 {
7436 Error("llDialog", "At least 1 button must be shown"); 7902 Error("llDialog", "At least 1 button must be shown");
7437 return; 7903 return;
7438 } 7904 }
7439 if (buttons.Length > 12) 7905 if (length > 12)
7440 { 7906 {
7441 Error("llDialog", "No more than 12 buttons can be shown"); 7907 Error("llDialog", "No more than 12 buttons can be shown");
7442 return; 7908 return;
7443 } 7909 }
7444 string[] buts = new string[buttons.Length]; 7910
7445 for (int i = 0; i < buttons.Length; i++) 7911 if (message == string.Empty)
7912 {
7913 Error("llDialog", "Empty message");
7914 }
7915 else if (Encoding.UTF8.GetByteCount(message) > 512)
7916 {
7917 Error("llDialog", "Message longer than 512 bytes");
7918 }
7919
7920 string[] buts = new string[length];
7921 for (int i = 0; i < length; i++)
7446 { 7922 {
7447 if (buttons.Data[i].ToString() == String.Empty) 7923 if (buttons.Data[i].ToString() == String.Empty)
7448 { 7924 {
7449 Error("llDialog", "Button label cannot be blank"); 7925 Error("llDialog", "Button label cannot be blank");
7450 return; 7926 return;
7451 } 7927 }
7928/*
7452 if (buttons.Data[i].ToString().Length > 24) 7929 if (buttons.Data[i].ToString().Length > 24)
7453 { 7930 {
7454 Error("llDialog", "Button label cannot be longer than 24 characters"); 7931 Error("llDialog", "Button label cannot be longer than 24 characters");
7455 return; 7932 return;
7456 } 7933 }
7934*/
7457 buts[i] = buttons.Data[i].ToString(); 7935 buts[i] = buttons.Data[i].ToString();
7458 } 7936 }
7459 7937
@@ -7513,9 +7991,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7513 return; 7991 return;
7514 } 7992 }
7515 7993
7516 // the rest of the permission checks are done in RezScript, so check the pin there as well 7994 SceneObjectPart dest = World.GetSceneObjectPart(destId);
7517 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 7995 if (dest != null)
7996 {
7997 if ((item.BasePermissions & (uint)PermissionMask.Transfer) != 0 || dest.ParentGroup.RootPart.OwnerID == m_host.ParentGroup.RootPart.OwnerID)
7998 {
7999 // the rest of the permission checks are done in RezScript, so check the pin there as well
8000 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
7518 8001
8002 if ((item.BasePermissions & (uint)PermissionMask.Copy) == 0)
8003 m_host.Inventory.RemoveInventoryItem(item.ItemID);
8004 }
8005 }
7519 // this will cause the delay even if the script pin or permissions were wrong - seems ok 8006 // this will cause the delay even if the script pin or permissions were wrong - seems ok
7520 ScriptSleep(m_sleepMsOnRemoteLoadScriptPin); 8007 ScriptSleep(m_sleepMsOnRemoteLoadScriptPin);
7521 } 8008 }
@@ -7589,19 +8076,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7589 public LSL_String llMD5String(string src, int nonce) 8076 public LSL_String llMD5String(string src, int nonce)
7590 { 8077 {
7591 m_host.AddScriptLPS(1); 8078 m_host.AddScriptLPS(1);
7592 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 8079 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()), Encoding.UTF8);
7593 } 8080 }
7594 8081
7595 public LSL_String llSHA1String(string src) 8082 public LSL_String llSHA1String(string src)
7596 { 8083 {
7597 m_host.AddScriptLPS(1); 8084 m_host.AddScriptLPS(1);
7598 return Util.SHA1Hash(src).ToLower(); 8085 return Util.SHA1Hash(src, Encoding.UTF8).ToLower();
7599 } 8086 }
7600 8087
7601 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 8088 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
7602 { 8089 {
7603 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 8090 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7604 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 8091 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
8092 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8093 return shapeBlock;
7605 8094
7606 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 8095 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
7607 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 8096 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
@@ -7706,6 +8195,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7706 // Prim type box, cylinder and prism. 8195 // Prim type box, cylinder and prism.
7707 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) 8196 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve)
7708 { 8197 {
8198 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8199 return;
8200
7709 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 8201 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7710 ObjectShapePacket.ObjectDataBlock shapeBlock; 8202 ObjectShapePacket.ObjectDataBlock shapeBlock;
7711 8203
@@ -7759,6 +8251,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7759 // Prim type sphere. 8251 // Prim type sphere.
7760 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 8252 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
7761 { 8253 {
8254 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8255 return;
8256
7762 ObjectShapePacket.ObjectDataBlock shapeBlock; 8257 ObjectShapePacket.ObjectDataBlock shapeBlock;
7763 8258
7764 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 8259 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7805,6 +8300,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7805 // Prim type torus, tube and ring. 8300 // Prim type torus, tube and ring.
7806 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) 8301 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve)
7807 { 8302 {
8303 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8304 return;
8305
7808 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 8306 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7809 ObjectShapePacket.ObjectDataBlock shapeBlock; 8307 ObjectShapePacket.ObjectDataBlock shapeBlock;
7810 8308
@@ -7940,6 +8438,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7940 // Prim type sculpt. 8438 // Prim type sculpt.
7941 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 8439 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7942 { 8440 {
8441 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8442 return;
8443
7943 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 8444 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7944 UUID sculptId; 8445 UUID sculptId;
7945 8446
@@ -7962,7 +8463,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7962 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 8463 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7963 { 8464 {
7964 // default 8465 // default
7965 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 8466 type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7966 } 8467 }
7967 8468
7968 part.Shape.SetSculptProperties((byte)type, sculptId); 8469 part.Shape.SetSculptProperties((byte)type, sculptId);
@@ -7995,9 +8496,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7995 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 8496 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7996 } 8497 }
7997 8498
7998 protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 8499 private void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7999 { 8500 {
8000 SetEntityParams(GetLinkEntities(linknumber), rules, originFunc); 8501 List<object> parts = new List<object>();
8502 List<SceneObjectPart> prims = GetLinkParts(linknumber);
8503 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
8504 foreach (SceneObjectPart p in prims)
8505 parts.Add(p);
8506 foreach (ScenePresence p in avatars)
8507 parts.Add(p);
8508
8509 LSL_List remaining = new LSL_List();
8510 uint rulesParsed = 0;
8511
8512 if (parts.Count > 0)
8513 {
8514 foreach (object part in parts)
8515 {
8516 if (part is SceneObjectPart)
8517 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
8518 else
8519 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
8520 }
8521
8522 while (remaining.Length > 2)
8523 {
8524 linknumber = remaining.GetLSLIntegerItem(0);
8525 rules = remaining.GetSublist(1, -1);
8526 parts.Clear();
8527 prims = GetLinkParts(linknumber);
8528 avatars = GetLinkAvatars(linknumber);
8529 foreach (SceneObjectPart p in prims)
8530 parts.Add(p);
8531 foreach (ScenePresence p in avatars)
8532 parts.Add(p);
8533
8534 remaining = new LSL_List();
8535 foreach (object part in parts)
8536 {
8537 if (part is SceneObjectPart)
8538 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
8539 else
8540 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
8541 }
8542 }
8543 }
8001 } 8544 }
8002 8545
8003 protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc) 8546 protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc)
@@ -8176,11 +8719,81 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8176 } 8719 }
8177 } 8720 }
8178 8721
8722 public LSL_List llGetPhysicsMaterial()
8723 {
8724 LSL_List result = new LSL_List();
8725
8726 result.Add(new LSL_Float(m_host.GravityModifier));
8727 result.Add(new LSL_Float(m_host.Restitution));
8728 result.Add(new LSL_Float(m_host.Friction));
8729 result.Add(new LSL_Float(m_host.Density));
8730
8731 return result;
8732 }
8733
8734 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
8735 float material_density, float material_friction,
8736 float material_restitution, float material_gravity_modifier)
8737 {
8738 ExtraPhysicsData physdata = new ExtraPhysicsData();
8739 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
8740 physdata.Density = part.Density;
8741 physdata.Friction = part.Friction;
8742 physdata.Bounce = part.Restitution;
8743 physdata.GravitationModifier = part.GravityModifier;
8744
8745 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
8746 physdata.Density = material_density;
8747 if ((material_bits & (int)ScriptBaseClass.FRICTION) != 0)
8748 physdata.Friction = material_friction;
8749 if ((material_bits & (int)ScriptBaseClass.RESTITUTION) != 0)
8750 physdata.Bounce = material_restitution;
8751 if ((material_bits & (int)ScriptBaseClass.GRAVITY_MULTIPLIER) != 0)
8752 physdata.GravitationModifier = material_gravity_modifier;
8753
8754 part.UpdateExtraPhysics(physdata);
8755 }
8756
8757 public void llSetPhysicsMaterial(int material_bits,
8758 float material_gravity_modifier, float material_restitution,
8759 float material_friction, float material_density)
8760 {
8761 SetPhysicsMaterial(m_host, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
8762 }
8763
8764 // vector up using libomv (c&p from sop )
8765 // vector up rotated by r
8766 private Vector3 Zrot(Quaternion r)
8767 {
8768 double x, y, z, m;
8769
8770 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
8771 if (Math.Abs(1.0 - m) > 0.000001)
8772 {
8773 m = 1.0 / Math.Sqrt(m);
8774 r.X *= (float)m;
8775 r.Y *= (float)m;
8776 r.Z *= (float)m;
8777 r.W *= (float)m;
8778 }
8779
8780 x = 2 * (r.X * r.Z + r.Y * r.W);
8781 y = 2 * (-r.X * r.W + r.Y * r.Z);
8782 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
8783
8784 return new Vector3((float)x, (float)y, (float)z);
8785 }
8786
8179 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) 8787 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
8180 { 8788 {
8789 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8790 return new LSL_List();
8791
8181 int idx = 0; 8792 int idx = 0;
8182 int idxStart = 0; 8793 int idxStart = 0;
8183 8794
8795 SceneObjectGroup parentgrp = part.ParentGroup;
8796
8184 bool positionChanged = false; 8797 bool positionChanged = false;
8185 LSL_Vector currentPosition = GetPartLocalPos(part); 8798 LSL_Vector currentPosition = GetPartLocalPos(part);
8186 8799
@@ -8216,8 +8829,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8216 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); 8829 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1));
8217 return new LSL_List(); 8830 return new LSL_List();
8218 } 8831 }
8832 if (part.IsRoot && !part.ParentGroup.IsAttachment)
8833 currentPosition = GetSetPosTarget(part, v, currentPosition, true);
8834 else
8835 currentPosition = GetSetPosTarget(part, v, currentPosition, false);
8219 positionChanged = true; 8836 positionChanged = true;
8220 currentPosition = GetSetPosTarget(part, v, currentPosition);
8221 8837
8222 break; 8838 break;
8223 case ScriptBaseClass.PRIM_SIZE: 8839 case ScriptBaseClass.PRIM_SIZE:
@@ -8242,7 +8858,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8242 return new LSL_List(); 8858 return new LSL_List();
8243 } 8859 }
8244 // try to let this work as in SL... 8860 // try to let this work as in SL...
8245 if (part.ParentID == 0) 8861 if (part.ParentID == 0 || (part.ParentGroup != null && part == part.ParentGroup.RootPart))
8246 { 8862 {
8247 // special case: If we are root, rotate complete SOG to new rotation 8863 // special case: If we are root, rotate complete SOG to new rotation
8248 SetRot(part, q); 8864 SetRot(part, q);
@@ -9243,7 +9859,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9243 9859
9244 break; 9860 break;
9245 9861
9246 case ScriptBaseClass.PRIM_TEMP_ON_REZ: 9862 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
9863 if (remain < 5)
9864 return new LSL_List();
9865
9866 int material_bits = rules.GetLSLIntegerItem(idx++);
9867 float material_density = (float)rules.GetLSLFloatItem(idx++);
9868 float material_friction = (float)rules.GetLSLFloatItem(idx++);
9869 float material_restitution = (float)rules.GetLSLFloatItem(idx++);
9870 float material_gravity_modifier = (float)rules.GetLSLFloatItem(idx++);
9871
9872 SetPhysicsMaterial(part, material_bits, material_density, material_friction, material_restitution, material_gravity_modifier);
9873
9874 break;
9875
9876 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
9247 if (remain < 1) 9877 if (remain < 1)
9248 return new LSL_List(); 9878 return new LSL_List();
9249 string temp = rules.Data[idx++].ToString(); 9879 string temp = rules.Data[idx++].ToString();
@@ -9437,14 +10067,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9437 if (part.ParentGroup.RootPart == part) 10067 if (part.ParentGroup.RootPart == part)
9438 { 10068 {
9439 SceneObjectGroup parent = part.ParentGroup; 10069 SceneObjectGroup parent = part.ParentGroup;
9440 parent.UpdateGroupPosition(currentPosition); 10070// Util.FireAndForget(delegate(object x) {
10071 parent.UpdateGroupPosition(currentPosition);
10072// });
9441 } 10073 }
9442 else 10074 else
9443 { 10075 {
9444 part.OffsetPosition = currentPosition; 10076 part.OffsetPosition = currentPosition;
9445 SceneObjectGroup parent = part.ParentGroup; 10077// SceneObjectGroup parent = part.ParentGroup;
9446 parent.HasGroupChanged = true; 10078// parent.HasGroupChanged = true;
9447 parent.ScheduleGroupForTerseUpdate(); 10079// parent.ScheduleGroupForTerseUpdate();
10080 part.ScheduleTerseUpdate();
9448 } 10081 }
9449 } 10082 }
9450 } 10083 }
@@ -9511,7 +10144,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9511 SceneObjectPart parentPart = sp.ParentPart; 10144 SceneObjectPart parentPart = sp.ParentPart;
9512 10145
9513 if (parentPart != null) 10146 if (parentPart != null)
9514 sp.Rotation = m_host.GetWorldRotation() * inRot; 10147 sp.Rotation = m_host.GetWorldRotation() * inRot;
9515 10148
9516 break; 10149 break;
9517 10150
@@ -9596,10 +10229,104 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9596 10229
9597 public LSL_String llXorBase64Strings(string str1, string str2) 10230 public LSL_String llXorBase64Strings(string str1, string str2)
9598 { 10231 {
10232 int padding = 0;
10233
10234 string b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
10235
10236 ScriptSleep(300);
9599 m_host.AddScriptLPS(1); 10237 m_host.AddScriptLPS(1);
9600 Deprecated("llXorBase64Strings", "Use llXorBase64 instead"); 10238
9601 ScriptSleep(m_sleepMsOnXorBase64Strings); 10239 if (str1 == String.Empty)
9602 return String.Empty; 10240 return String.Empty;
10241 if (str2 == String.Empty)
10242 return str1;
10243
10244 int len = str2.Length;
10245 if ((len % 4) != 0) // LL is EVIL!!!!
10246 {
10247 while (str2.EndsWith("="))
10248 str2 = str2.Substring(0, str2.Length - 1);
10249
10250 len = str2.Length;
10251 int mod = len % 4;
10252
10253 if (mod == 1)
10254 str2 = str2.Substring(0, str2.Length - 1);
10255 else if (mod == 2)
10256 str2 += "==";
10257 else if (mod == 3)
10258 str2 += "=";
10259 }
10260
10261 byte[] data1;
10262 byte[] data2;
10263 try
10264 {
10265 data1 = Convert.FromBase64String(str1);
10266 data2 = Convert.FromBase64String(str2);
10267 }
10268 catch (Exception)
10269 {
10270 return new LSL_String(String.Empty);
10271 }
10272
10273 // For cases where the decoded length of s2 is greater
10274 // than the decoded length of s1, simply perform a normal
10275 // decode and XOR
10276 //
10277 /*
10278 if (data2.Length >= data1.Length)
10279 {
10280 for (int pos = 0 ; pos < data1.Length ; pos++ )
10281 data1[pos] ^= data2[pos];
10282
10283 return Convert.ToBase64String(data1);
10284 }
10285 */
10286
10287 // Remove padding
10288 while (str1.EndsWith("="))
10289 {
10290 str1 = str1.Substring(0, str1.Length - 1);
10291 padding++;
10292 }
10293 while (str2.EndsWith("="))
10294 str2 = str2.Substring(0, str2.Length - 1);
10295
10296 byte[] d1 = new byte[str1.Length];
10297 byte[] d2 = new byte[str2.Length];
10298
10299 for (int i = 0 ; i < str1.Length ; i++)
10300 {
10301 int idx = b64.IndexOf(str1.Substring(i, 1));
10302 if (idx == -1)
10303 idx = 0;
10304 d1[i] = (byte)idx;
10305 }
10306
10307 for (int i = 0 ; i < str2.Length ; i++)
10308 {
10309 int idx = b64.IndexOf(str2.Substring(i, 1));
10310 if (idx == -1)
10311 idx = 0;
10312 d2[i] = (byte)idx;
10313 }
10314
10315 string output = String.Empty;
10316
10317 for (int pos = 0 ; pos < d1.Length ; pos++)
10318 output += b64[d1[pos] ^ d2[pos % d2.Length]];
10319
10320 // Here's a funny thing: LL blithely violate the base64
10321 // standard pretty much everywhere. Here, padding is
10322 // added only if the first input string had it, rather
10323 // than when the data actually needs it. This can result
10324 // in invalid base64 being returned. Go figure.
10325
10326 while (padding-- > 0)
10327 output += "=";
10328
10329 return output;
9603 } 10330 }
9604 10331
9605 public void llRemoteDataSetRegion() 10332 public void llRemoteDataSetRegion()
@@ -9742,188 +10469,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9742 public LSL_List llGetBoundingBox(string obj) 10469 public LSL_List llGetBoundingBox(string obj)
9743 { 10470 {
9744 m_host.AddScriptLPS(1); 10471 m_host.AddScriptLPS(1);
9745
9746 // Get target avatar if non-seated avatar or attachment, or prim and object
9747 UUID objID = UUID.Zero; 10472 UUID objID = UUID.Zero;
9748 UUID.TryParse(obj, out objID);
9749 ScenePresence agent = World.GetScenePresence(objID);
9750 if (agent != null)
9751 {
9752 if (agent.ParentPart != null)
9753 {
9754 objID = agent.ParentPart.UUID;
9755 agent = null;
9756 }
9757 }
9758 SceneObjectGroup group = null;
9759 SceneObjectPart target = World.GetSceneObjectPart(objID);
9760 if (target != null)
9761 {
9762 group = target.ParentGroup;
9763 if (group.IsAttachment) {
9764 objID = group.AttachedAvatar;
9765 agent = World.GetScenePresence(objID);
9766 group = null;
9767 target = null;
9768 }
9769 }
9770
9771 // Initialize but break if no target
9772 LSL_List result = new LSL_List(); 10473 LSL_List result = new LSL_List();
9773 int groupCount = 0; 10474
9774 int partCount = 0; 10475 // If the ID is not valid, return null result
9775 int vertexCount = 0; 10476 if (!UUID.TryParse(obj, out objID))
9776 if (target == null && agent == null)
9777 { 10477 {
9778 result.Add(new LSL_Vector()); 10478 result.Add(new LSL_Vector());
9779 result.Add(new LSL_Vector()); 10479 result.Add(new LSL_Vector());
9780 if (m_addStatsInGetBoundingBox)
9781 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9782 return result; 10480 return result;
9783 } 10481 }
9784 Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
9785 Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue);
9786 10482
9787 // Try to get a mesher 10483 // Check if this is an attached prim. If so, replace
9788 IRendering primMesher = null; 10484 // the UUID with the avatar UUID and report it's bounding box
9789 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 10485 SceneObjectPart part = World.GetSceneObjectPart(objID);
9790 if (renderers.Count > 0) 10486 if (part != null && part.ParentGroup.IsAttachment)
9791 primMesher = RenderingLoader.LoadRenderer(renderers[0]); 10487 objID = part.ParentGroup.AttachedAvatar;
9792 10488
9793 // Get bounding box of just avatar, seated or not 10489 // Find out if this is an avatar ID. If so, return it's box
9794 if (agent != null) 10490 ScenePresence presence = World.GetScenePresence(objID);
9795 { 10491 if (presence != null)
9796 bool hasParent = false;
9797 Vector3 lower;
9798 Vector3 upper;
9799 BoundingBoxOfScenePresence(agent, out lower, out upper);
9800 Vector3 offset = Vector3.Zero;
9801
9802 // Since local bounding box unrotated and untilted, keep it simple
9803 AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9804 partCount++;
9805 groupCount++;
9806
9807 // Return lower and upper bounding box corners
9808 result.Add(new LSL_Vector(minPosition));
9809 result.Add(new LSL_Vector(maxPosition));
9810 if (m_addStatsInGetBoundingBox)
9811 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9812 return result;
9813 }
9814 // Get bounding box of object including seated avatars
9815 else if (group != null)
9816 { 10492 {
9817 // Merge bounding boxes of all parts (prims and mesh) 10493 // As per LSL Wiki, there is no difference between sitting
9818 foreach (SceneObjectPart part in group.Parts) 10494 // and standing avatar since server 1.36
9819 { 10495 LSL_Vector lower;
9820 bool hasParent = (!part.IsRoot); 10496 LSL_Vector upper;
9821 // When requested or if no mesher, keep it simple
9822 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null)
9823 {
9824 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9825 }
9826 // Do the full mounty
9827 else
9828 {
9829 Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset);
9830 byte[] sculptAsset = null;
9831 if (omvPrim.Sculpt != null)
9832 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
9833
9834 // When part is mesh
9835 // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler.
9836 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
9837 {
9838 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
9839 FacetedMesh mesh = null;
9840 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh);
9841 meshAsset = null;
9842 if (mesh != null)
9843 {
9844 AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9845 mesh = null;
9846 }
9847 }
9848
9849 // When part is sculpt
9850 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
9851 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
9852 {
9853 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
9854 if (imgDecoder != null)
9855 {
9856 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
9857 if (sculpt != null)
9858 {
9859 SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium);
9860 sculpt.Dispose();
9861 if (mesh != null)
9862 {
9863 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9864 mesh = null;
9865 }
9866 }
9867 }
9868 }
9869 10497
9870 // When part is prim 10498 Vector3 box = presence.Appearance.AvatarBoxSize * 0.5f;
9871 else if (omvPrim.Sculpt == null)
9872 {
9873 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9874 if (mesh != null)
9875 {
9876 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9877 mesh = null;
9878 }
9879 }
9880 10499
9881 // When all else fails, try fallback to simple box 10500 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
9882 else 10501 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
9883 { 10502/*
9884 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 10503 {
9885 } 10504 // This is for ground sitting avatars
9886 } 10505 float height = presence.Appearance.AvatarHeight / 2.66666667f;
9887 partCount++; 10506 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
10507 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
10508 }
10509 else
10510 {
10511 // This is for standing/flying avatars
10512 float height = presence.Appearance.AvatarHeight / 2.0f;
10513 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f);
10514 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f);
9888 } 10515 }
9889 }
9890
9891 // Merge bounding boxes of seated avatars
9892 foreach (ScenePresence sp in group.GetSittingAvatars())
9893 {
9894 Vector3 lower;
9895 Vector3 upper;
9896 BoundingBoxOfScenePresence(sp, out lower, out upper);
9897 Vector3 offset = sp.OffsetPosition;
9898 10516
9899 bool hasParent = true; 10517 // Adjust to the documented error offsets (see LSL Wiki)
9900 // When requested or if no mesher, keep it simple 10518 lower += new LSL_Vector(0.05f, 0.05f, 0.05f);
9901 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) 10519 upper -= new LSL_Vector(0.05f, 0.05f, 0.05f);
10520*/
9902 { 10521 {
9903 AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 10522 // This is for ground sitting avatars TODO!
10523 lower = new LSL_Vector(-box.X - 0.1125, -box.Y, box.Z * -1.0f);
10524 upper = new LSL_Vector(box.X + 0.1125, box.Y, box.Z * -1.0f);
9904 } 10525 }
9905 // Do the full mounty
9906 else 10526 else
9907 { 10527 {
9908 // Prim shapes don't do center offsets, so add it here. 10528 // This is for standing/flying avatars
9909 offset = offset + (lower + upper) * 0.5f * sp.Rotation; 10529 lower = new LSL_Vector(-box.X, -box.Y, -box.Z);
9910 Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE); 10530 upper = new LSL_Vector(box.X, box.Y, box.Z);
9911 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9912 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9913 mesh = null;
9914 } 10531 }
9915 partCount++; 10532
10533 if (lower.x > upper.x)
10534 lower.x = upper.x;
10535 if (lower.y > upper.y)
10536 lower.y = upper.y;
10537 if (lower.z > upper.z)
10538 lower.z = upper.z;
10539
10540 result.Add(lower);
10541 result.Add(upper);
10542 return result;
9916 } 10543 }
9917 10544
9918 groupCount++; 10545 part = World.GetSceneObjectPart(objID);
10546 // Currently only works for single prims without a sitting avatar
10547 if (part != null)
10548 {
10549 float minX;
10550 float maxX;
10551 float minY;
10552 float maxY;
10553 float minZ;
10554 float maxZ;
9919 10555
9920 // Return lower and upper bounding box corners 10556 // This BBox is in sim coordinates, with the offset being
9921 result.Add(new LSL_Vector(minPosition)); 10557 // a contained point.
9922 result.Add(new LSL_Vector(maxPosition)); 10558 Vector3[] offsets = Scene.GetCombinedBoundingBox(new List<SceneObjectGroup> { part.ParentGroup },
9923 if (m_addStatsInGetBoundingBox) 10559 out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
9924 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); 10560
10561 minX -= offsets[0].X;
10562 maxX -= offsets[0].X;
10563 minY -= offsets[0].Y;
10564 maxY -= offsets[0].Y;
10565 minZ -= offsets[0].Z;
10566 maxZ -= offsets[0].Z;
10567
10568 LSL_Vector lower;
10569 LSL_Vector upper;
10570
10571 // Adjust to the documented error offsets (see LSL Wiki)
10572 lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f);
10573 upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f);
10574
10575 if (lower.x > upper.x)
10576 lower.x = upper.x;
10577 if (lower.y > upper.y)
10578 lower.y = upper.y;
10579 if (lower.z > upper.z)
10580 lower.z = upper.z;
10581
10582 result.Add(lower);
10583 result.Add(upper);
10584 return result;
10585 }
9925 10586
9926 primMesher = null; 10587 // Not found so return empty values
10588 result.Add(new LSL_Vector());
10589 result.Add(new LSL_Vector());
9927 return result; 10590 return result;
9928 } 10591 }
9929 10592
@@ -9963,425 +10626,71 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9963 } 10626 }
9964 } 10627 }
9965 10628
9966 /// <summary>
9967 /// Helper to approximate a part with a simple box.
9968 /// </summary>
9969 private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9970 {
9971 // Parse the 8 box corners
9972 for (int i = 0; i < 8; i++)
9973 {
9974 // Calculate each box corner
9975 Vector3 position = corner1;
9976 if ((i & 1) != 0)
9977 position.X = corner2.X;
9978 if ((i & 2) != 0)
9979 position.Y = corner2.Y;
9980 if ((i & 4) != 0)
9981 position.Z = corner2.Z;
9982 // Rotate part unless part is root
9983 if (hasParent)
9984 position = position * rotation;
9985 position = position + offset;
9986 // Adjust lower and upper bounding box corners if needed
9987 lower = Vector3.Min(lower, position);
9988 upper = Vector3.Max(upper, position);
9989 count++;
9990 }
9991 }
9992
9993 /// <summary>
9994 /// Helper to parse a meshed prim and needed especially
9995 /// for accuracy with tortured prims and sculpts.
9996 /// </summary>
9997 private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9998 {
9999 // Quirk: A meshed box contains 10 instead of the 8 necessary vertices.
10000 if (mesh != null)
10001 {
10002 // Parse each vertex in mesh
10003 foreach (Vertex vertex in mesh.Vertices)
10004 {
10005 Vector3 position = vertex.Position;
10006 position = position * prim.Scale;
10007 // Rotate part unless part is root
10008 if (hasParent)
10009 position = position * prim.Rotation;
10010 position = position + prim.Position;
10011 // Adjust lower and upper bounding box corners if needed
10012 lower = Vector3.Min(lower, position);
10013 upper = Vector3.Max(upper, position);
10014 count++;
10015 }
10016 }
10017 }
10018
10019 /// <summary>
10020 /// Helper to parse mesh because no method exists
10021 /// to parse mesh assets to SimpleMesh.
10022 /// </summary>
10023 private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
10024 {
10025 if (mesh != null)
10026 {
10027 // Parse each face in mesh
10028 // since vertex array isn't populated.
10029 // This parses each unique vertex 3-6 times.
10030 foreach (Face face in mesh.Faces)
10031 {
10032 // Parse each vertex in face
10033 foreach (Vertex vertex in face.Vertices)
10034 {
10035 Vector3 position = vertex.Position;
10036 position = position * prim.Scale;
10037 // Rotate part unless part is root
10038 if (hasParent)
10039 position = position * prim.Rotation;
10040 position = position + prim.Position;
10041 // Adjust lower and upper bounding box corners if needed
10042 lower = Vector3.Min(lower, position);
10043 upper = Vector3.Max(upper, position);
10044 count++;
10045 }
10046 }
10047 }
10048 }
10049
10050 /// <summary>
10051 /// Helper to make up an OpenMetaverse prim
10052 /// needed to create mesh from parts.
10053 /// </summary>
10054 private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType)
10055 {
10056 // Initialize and set common parameters
10057 Primitive prim = new OpenMetaverse.Primitive();
10058 prim.Scale = scale;
10059 prim.Position = position;
10060 prim.Rotation = rotation;
10061 prim.PrimData.PathShearX = 0.0f;
10062 prim.PrimData.PathShearY = 0.0f;
10063 prim.PrimData.PathBegin = 0.0f;
10064 prim.PrimData.PathEnd = 1.0f;
10065 prim.PrimData.PathScaleX = 1.0f;
10066 prim.PrimData.PathScaleY = 1.0f;
10067 prim.PrimData.PathTaperX = 0.0f;
10068 prim.PrimData.PathTaperY = 0.0f;
10069 prim.PrimData.PathTwistBegin = 0.0f;
10070 prim.PrimData.PathTwist = 0.0f;
10071 prim.PrimData.ProfileBegin = 0.0f;
10072 prim.PrimData.ProfileEnd = 1.0f;
10073 prim.PrimData.ProfileHollow = 0.0f;
10074 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10075 prim.PrimData.ProfileHole = (HoleType)0;
10076 prim.PrimData.PathCurve = (PathCurve)16;
10077 prim.PrimData.PathRadiusOffset = 0.0f;
10078 prim.PrimData.PathRevolutions = 1.0f;
10079 prim.PrimData.PathSkew = 0.0f;
10080 prim.PrimData.PCode = OpenMetaverse.PCode.Prim;
10081 prim.PrimData.State = (byte)0;
10082
10083 // Set type specific parameters
10084 switch (primType)
10085 {
10086 // Set specific parameters for box
10087 case ScriptBaseClass.PRIM_TYPE_BOX:
10088 prim.PrimData.PathScaleY = 1.0f;
10089 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10090 prim.PrimData.PathCurve = (PathCurve)16;
10091 break;
10092 // Set specific parameters for cylinder
10093 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
10094 prim.PrimData.PathScaleY = 1.0f;
10095 prim.PrimData.ProfileCurve = (ProfileCurve)0;
10096 prim.PrimData.PathCurve = (PathCurve)16;
10097 break;
10098 // Set specific parameters for prism
10099 case ScriptBaseClass.PRIM_TYPE_PRISM:
10100 prim.PrimData.PathScaleY = 1.0f;
10101 prim.PrimData.ProfileCurve = (ProfileCurve)3;
10102 prim.PrimData.PathCurve = (PathCurve)16;
10103 break;
10104 // Set specific parameters for sphere
10105 case ScriptBaseClass.PRIM_TYPE_SPHERE:
10106 prim.PrimData.PathScaleY = 1.0f;
10107 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10108 prim.PrimData.PathCurve = (PathCurve)32;
10109 break;
10110 // Set specific parameters for torus
10111 case ScriptBaseClass.PRIM_TYPE_TORUS:
10112 prim.PrimData.PathScaleY = 0.5f;
10113 prim.PrimData.ProfileCurve = (ProfileCurve)0;
10114 prim.PrimData.PathCurve = (PathCurve)32;
10115 break;
10116 // Set specific parameters for tube
10117 case ScriptBaseClass.PRIM_TYPE_TUBE:
10118 prim.PrimData.PathScaleY = 0.5f;
10119 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10120 prim.PrimData.PathCurve = (PathCurve)32;
10121 break;
10122 // Set specific parameters for ring
10123 case ScriptBaseClass.PRIM_TYPE_RING:
10124 prim.PrimData.PathScaleY = 0.5f;
10125 prim.PrimData.ProfileCurve = (ProfileCurve)3;
10126 prim.PrimData.PathCurve = (PathCurve)32;
10127 break;
10128 // Set specific parameters for sculpt
10129 case ScriptBaseClass.PRIM_TYPE_SCULPT:
10130 prim.PrimData.PathScaleY = 1.0f;
10131 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10132 prim.PrimData.PathCurve = (PathCurve)32;
10133 break;
10134 // Default to specific parameters for box
10135 default:
10136 prim.PrimData.PathScaleY = 1.0f;
10137 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10138 prim.PrimData.PathCurve = (PathCurve)16;
10139 break;
10140 }
10141 10629
10142 return prim;
10143 }
10144
10145 /// <summary>
10146 /// Implementation of llGetGeometricCenter according to SL 2015-04-30.
10147 /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter
10148 /// Returns the average position offset of all linked parts,
10149 /// including the root prim and seated avatars,
10150 /// relative to the root prim in local coordinates.
10151 /// </summary>
10152 public LSL_Vector llGetGeometricCenter() 10630 public LSL_Vector llGetGeometricCenter()
10153 { 10631 {
10154 // Subtract whatever position the root prim has to make it zero 10632 return new LSL_Vector(m_host.GetGeometricCenter());
10155 Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f;
10156
10157 // Add all prim/part position offsets
10158 foreach (SceneObjectPart part in m_host.ParentGroup.Parts)
10159 offset = offset + part.OffsetPosition;
10160 // Add all avatar/scene presence position offsets
10161 foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars())
10162 offset = offset + sp.OffsetPosition;
10163
10164 // Calculate and return the average offset
10165 offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount());
10166 return new LSL_Vector(offset);
10167 } 10633 }
10168 10634
10169 public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) 10635 public LSL_List llGetPrimitiveParams(LSL_List rules)
10170 { 10636 {
10171 LSL_List result = new LSL_List(); 10637 m_host.AddScriptLPS(1);
10172 LSL_List remaining;
10173
10174 while (true)
10175 {
10176// m_log.DebugFormat(
10177// "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}",
10178// rules.Length, entity != null ? entity.Name : "NULL");
10179
10180 if (entity == null)
10181 return result;
10182 10638
10183 if (entity is SceneObjectPart) 10639 LSL_List result = new LSL_List();
10184 remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result);
10185 else
10186 remaining = GetAgentParams((ScenePresence)entity, rules, ref result);
10187 10640
10188 if (remaining == null || remaining.Length < 2) 10641 LSL_List remaining = GetPrimParams(m_host, rules, ref result);
10189 return result;
10190 10642
10643 while ((object)remaining != null && remaining.Length > 2)
10644 {
10191 int linknumber = remaining.GetLSLIntegerItem(0); 10645 int linknumber = remaining.GetLSLIntegerItem(0);
10192 rules = remaining.GetSublist(1, -1); 10646 rules = remaining.GetSublist(1, -1);
10193 entity = GetLinkEntity(m_host, linknumber); 10647 List<SceneObjectPart> parts = GetLinkParts(linknumber);
10194 }
10195 }
10196 10648
10197 public LSL_List llGetPrimitiveParams(LSL_List rules) 10649 foreach (SceneObjectPart part in parts)
10198 { 10650 remaining = GetPrimParams(part, rules, ref result);
10199 m_host.AddScriptLPS(1); 10651 }
10200 10652
10201 return GetEntityParams(m_host, rules); 10653 return result;
10202 } 10654 }
10203 10655
10204 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 10656 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
10205 { 10657 {
10206 m_host.AddScriptLPS(1); 10658 m_host.AddScriptLPS(1);
10207 10659
10208 return GetEntityParams(GetLinkEntity(m_host, linknumber), rules); 10660 // acording to SL wiki this must indicate a single link number or link_root or link_this.
10209 } 10661 // keep other options as before
10210 10662
10211 public LSL_Vector GetAgentSize(ScenePresence sp) 10663 List<SceneObjectPart> parts;
10212 { 10664 List<ScenePresence> avatars;
10213 return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight); 10665
10214 } 10666 LSL_List res = new LSL_List();
10667 LSL_List remaining = new LSL_List();
10215 10668
10216 /// <summary> 10669 while (rules.Length > 0)
10217 /// Gets params for a seated avatar in a linkset.
10218 /// </summary>
10219 /// <returns></returns>
10220 /// <param name='sp'></param>
10221 /// <param name='rules'></param>
10222 /// <param name='res'></param>
10223 public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res)
10224 {
10225 int idx = 0;
10226 while (idx < rules.Length)
10227 { 10670 {
10228 int code = (int)rules.GetLSLIntegerItem(idx++); 10671 parts = GetLinkParts(linknumber);
10229 int remain = rules.Length-idx; 10672 avatars = GetLinkAvatars(linknumber);
10230 10673
10231 switch (code) 10674 remaining = new LSL_List();
10675 foreach (SceneObjectPart part in parts)
10232 { 10676 {
10233 case (int)ScriptBaseClass.PRIM_MATERIAL: 10677 remaining = GetPrimParams(part, rules, ref res);
10234 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH)); 10678 }
10235 break; 10679 foreach (ScenePresence avatar in avatars)
10236 10680 {
10237 case (int)ScriptBaseClass.PRIM_PHYSICS: 10681 remaining = GetPrimParams(avatar, rules, ref res);
10238 res.Add(ScriptBaseClass.FALSE); 10682 }
10239 break;
10240
10241 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
10242 res.Add(ScriptBaseClass.FALSE);
10243 break;
10244
10245 case (int)ScriptBaseClass.PRIM_PHANTOM:
10246 res.Add(ScriptBaseClass.FALSE);
10247 break;
10248
10249 case (int)ScriptBaseClass.PRIM_POSITION:
10250 res.Add(new LSL_Vector(sp.AbsolutePosition));
10251 break;
10252
10253 case (int)ScriptBaseClass.PRIM_SIZE:
10254 res.Add(GetAgentSize(sp));
10255 break;
10256
10257 case (int)ScriptBaseClass.PRIM_ROTATION:
10258 res.Add(sp.GetWorldRotation());
10259 break;
10260
10261 case (int)ScriptBaseClass.PRIM_TYPE:
10262 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
10263 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
10264 res.Add(new LSL_Vector(0, 1, 0));
10265 res.Add(new LSL_Float(0));
10266 res.Add(new LSL_Vector(0, 0, 0));
10267 res.Add(new LSL_Vector(1, 1, 0));
10268 res.Add(new LSL_Vector(0, 0, 0));
10269 break;
10270
10271 case (int)ScriptBaseClass.PRIM_TEXTURE:
10272 if (remain < 1)
10273 return new LSL_List();
10274
10275 int face = (int)rules.GetLSLIntegerItem(idx++);
10276 if (face > 21)
10277 break;
10278
10279 res.Add(new LSL_String(""));
10280 res.Add(ScriptBaseClass.ZERO_VECTOR);
10281 res.Add(ScriptBaseClass.ZERO_VECTOR);
10282 res.Add(new LSL_Float(0));
10283 break;
10284
10285 case (int)ScriptBaseClass.PRIM_COLOR:
10286 if (remain < 1)
10287 return new LSL_List();
10288
10289 face = (int)rules.GetLSLIntegerItem(idx++);
10290 if (face > 21)
10291 break;
10292
10293 res.Add(ScriptBaseClass.ZERO_VECTOR);
10294 res.Add(new LSL_Float(0));
10295 break;
10296
10297 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
10298 if (remain < 1)
10299 return new LSL_List();
10300
10301 face = (int)rules.GetLSLIntegerItem(idx++);
10302 if (face > 21)
10303 break;
10304
10305 res.Add(ScriptBaseClass.PRIM_SHINY_NONE);
10306 res.Add(ScriptBaseClass.PRIM_BUMP_NONE);
10307 break;
10308
10309 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
10310 if (remain < 1)
10311 return new LSL_List();
10312
10313 face = (int)rules.GetLSLIntegerItem(idx++);
10314 if (face > 21)
10315 break;
10316
10317 res.Add(ScriptBaseClass.FALSE);
10318 break;
10319
10320 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
10321 res.Add(ScriptBaseClass.FALSE);
10322 res.Add(new LSL_Integer(0));
10323 res.Add(new LSL_Float(0));
10324 res.Add(new LSL_Float(0));
10325 res.Add(new LSL_Float(0));
10326 res.Add(new LSL_Float(0));
10327 res.Add(ScriptBaseClass.ZERO_VECTOR);
10328 break;
10329
10330 case (int)ScriptBaseClass.PRIM_TEXGEN:
10331 if (remain < 1)
10332 return new LSL_List();
10333
10334 face = (int)rules.GetLSLIntegerItem(idx++);
10335 if (face > 21)
10336 break;
10337
10338 res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT);
10339 break;
10340
10341 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
10342 res.Add(ScriptBaseClass.FALSE);
10343 res.Add(ScriptBaseClass.ZERO_VECTOR);
10344 res.Add(ScriptBaseClass.ZERO_VECTOR);
10345 break;
10346
10347 case (int)ScriptBaseClass.PRIM_GLOW:
10348 if (remain < 1)
10349 return new LSL_List();
10350
10351 face = (int)rules.GetLSLIntegerItem(idx++);
10352 if (face > 21)
10353 break;
10354
10355 res.Add(new LSL_Float(0));
10356 break;
10357
10358 case (int)ScriptBaseClass.PRIM_TEXT:
10359 res.Add(new LSL_String(""));
10360 res.Add(ScriptBaseClass.ZERO_VECTOR);
10361 res.Add(new LSL_Float(1));
10362 break;
10363
10364 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
10365 res.Add(new LSL_Rotation(sp.Rotation));
10366 break;
10367
10368 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
10369 res.Add(new LSL_Vector(sp.OffsetPosition));
10370 break;
10371
10372 case (int)ScriptBaseClass.PRIM_SLICE:
10373 res.Add(new LSL_Vector(0, 1, 0));
10374 break;
10375
10376 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
10377 if(remain < 3)
10378 return new LSL_List();
10379 10683
10380 return rules.GetSublist(idx, -1); 10684 if (remaining.Length > 0)
10685 {
10686 linknumber = remaining.GetLSLIntegerItem(0);
10687 rules = remaining.GetSublist(1, -1);
10381 } 10688 }
10689 else
10690 break;
10382 } 10691 }
10383 10692
10384 return new LSL_List(); 10693 return res;
10385 } 10694 }
10386 10695
10387 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) 10696 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
@@ -10420,19 +10729,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10420 break; 10729 break;
10421 10730
10422 case (int)ScriptBaseClass.PRIM_POSITION: 10731 case (int)ScriptBaseClass.PRIM_POSITION:
10423 LSL_Vector v = new LSL_Vector(part.AbsolutePosition); 10732 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X,
10424 10733 part.AbsolutePosition.Y,
10425 // For some reason, the part.AbsolutePosition.* values do not change if the 10734 part.AbsolutePosition.Z);
10426 // linkset is rotated; they always reflect the child prim's world position
10427 // as though the linkset is unrotated. This is incompatible behavior with SL's
10428 // implementation, so will break scripts imported from there (not to mention it
10429 // makes it more difficult to determine a child prim's actual inworld position).
10430 if (!part.IsRoot)
10431 {
10432 LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition);
10433 v = ((v - rootPos) * llGetRootRotation()) + rootPos;
10434 }
10435
10436 res.Add(v); 10735 res.Add(v);
10437 break; 10736 break;
10438 10737
@@ -10541,7 +10840,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10541 Primitive.TextureEntry tex = part.Shape.Textures; 10840 Primitive.TextureEntry tex = part.Shape.Textures;
10542 if (face == ScriptBaseClass.ALL_SIDES) 10841 if (face == ScriptBaseClass.ALL_SIDES)
10543 { 10842 {
10544 for (face = 0 ; face < GetNumberOfSides(part); face++) 10843 for (face = 0; face < GetNumberOfSides(part); face++)
10545 { 10844 {
10546 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10845 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10547 10846
@@ -10577,13 +10876,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10577 if (remain < 1) 10876 if (remain < 1)
10578 return new LSL_List(); 10877 return new LSL_List();
10579 10878
10580 face=(int)rules.GetLSLIntegerItem(idx++); 10879 face = (int)rules.GetLSLIntegerItem(idx++);
10581 10880
10582 tex = part.Shape.Textures; 10881 tex = part.Shape.Textures;
10583 Color4 texcolor; 10882 Color4 texcolor;
10584 if (face == ScriptBaseClass.ALL_SIDES) 10883 if (face == ScriptBaseClass.ALL_SIDES)
10585 { 10884 {
10586 for (face = 0 ; face < GetNumberOfSides(part); face++) 10885 for (face = 0; face < GetNumberOfSides(part); face++)
10587 { 10886 {
10588 texcolor = tex.GetFace((uint)face).RGBA; 10887 texcolor = tex.GetFace((uint)face).RGBA;
10589 res.Add(new LSL_Vector(texcolor.R, 10888 res.Add(new LSL_Vector(texcolor.R,
@@ -10606,30 +10905,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10606 if (remain < 1) 10905 if (remain < 1)
10607 return new LSL_List(); 10906 return new LSL_List();
10608 10907
10609 face=(int)rules.GetLSLIntegerItem(idx++); 10908 face = (int)rules.GetLSLIntegerItem(idx++);
10610 10909
10611 tex = part.Shape.Textures; 10910 tex = part.Shape.Textures;
10911 int shiny;
10612 if (face == ScriptBaseClass.ALL_SIDES) 10912 if (face == ScriptBaseClass.ALL_SIDES)
10613 { 10913 {
10614 for (face = 0; face < GetNumberOfSides(part); face++) 10914 for (face = 0; face < GetNumberOfSides(part); face++)
10615 { 10915 {
10616 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10916 Shininess shinyness = tex.GetFace((uint)face).Shiny;
10617 // Convert Shininess to PRIM_SHINY_* 10917 if (shinyness == Shininess.High)
10618 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 10918 {
10619 // PRIM_BUMP_* 10919 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
10620 res.Add(new LSL_Integer((int)texface.Bump)); 10920 }
10921 else if (shinyness == Shininess.Medium)
10922 {
10923 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
10924 }
10925 else if (shinyness == Shininess.Low)
10926 {
10927 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
10928 }
10929 else
10930 {
10931 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
10932 }
10933 res.Add(new LSL_Integer(shiny));
10934 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
10621 } 10935 }
10622 } 10936 }
10623 else 10937 else
10624 { 10938 {
10625 if (face >= 0 && face < GetNumberOfSides(part)) 10939 Shininess shinyness = tex.GetFace((uint)face).Shiny;
10940 if (shinyness == Shininess.High)
10626 { 10941 {
10627 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10942 shiny = ScriptBaseClass.PRIM_SHINY_HIGH;
10628 // Convert Shininess to PRIM_SHINY_* 10943 }
10629 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 10944 else if (shinyness == Shininess.Medium)
10630 // PRIM_BUMP_* 10945 {
10631 res.Add(new LSL_Integer((int)texface.Bump)); 10946 shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM;
10947 }
10948 else if (shinyness == Shininess.Low)
10949 {
10950 shiny = ScriptBaseClass.PRIM_SHINY_LOW;
10951 }
10952 else
10953 {
10954 shiny = ScriptBaseClass.PRIM_SHINY_NONE;
10632 } 10955 }
10956 res.Add(new LSL_Integer(shiny));
10957 res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump));
10633 } 10958 }
10634 break; 10959 break;
10635 10960
@@ -10640,21 +10965,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10640 face = (int)rules.GetLSLIntegerItem(idx++); 10965 face = (int)rules.GetLSLIntegerItem(idx++);
10641 10966
10642 tex = part.Shape.Textures; 10967 tex = part.Shape.Textures;
10968 int fullbright;
10643 if (face == ScriptBaseClass.ALL_SIDES) 10969 if (face == ScriptBaseClass.ALL_SIDES)
10644 { 10970 {
10645 for (face = 0; face < GetNumberOfSides(part); face++) 10971 for (face = 0; face < GetNumberOfSides(part); face++)
10646 { 10972 {
10647 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10973 if (tex.GetFace((uint)face).Fullbright == true)
10648 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 10974 {
10975 fullbright = ScriptBaseClass.TRUE;
10976 }
10977 else
10978 {
10979 fullbright = ScriptBaseClass.FALSE;
10980 }
10981 res.Add(new LSL_Integer(fullbright));
10649 } 10982 }
10650 } 10983 }
10651 else 10984 else
10652 { 10985 {
10653 if (face >= 0 && face < GetNumberOfSides(part)) 10986 if (tex.GetFace((uint)face).Fullbright == true)
10654 { 10987 {
10655 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10988 fullbright = ScriptBaseClass.TRUE;
10656 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 10989 }
10990 else
10991 {
10992 fullbright = ScriptBaseClass.FALSE;
10657 } 10993 }
10994 res.Add(new LSL_Integer(fullbright));
10658 } 10995 }
10659 break; 10996 break;
10660 10997
@@ -10676,27 +11013,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10676 break; 11013 break;
10677 11014
10678 case (int)ScriptBaseClass.PRIM_TEXGEN: 11015 case (int)ScriptBaseClass.PRIM_TEXGEN:
11016 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
10679 if (remain < 1) 11017 if (remain < 1)
10680 return new LSL_List(); 11018 return new LSL_List();
10681 11019
10682 face=(int)rules.GetLSLIntegerItem(idx++); 11020 face = (int)rules.GetLSLIntegerItem(idx++);
10683 11021
10684 tex = part.Shape.Textures; 11022 tex = part.Shape.Textures;
10685 if (face == ScriptBaseClass.ALL_SIDES) 11023 if (face == ScriptBaseClass.ALL_SIDES)
10686 { 11024 {
10687 for (face = 0; face < GetNumberOfSides(part); face++) 11025 for (face = 0; face < GetNumberOfSides(part); face++)
10688 { 11026 {
10689 MappingType texgen = tex.GetFace((uint)face).TexMapType; 11027 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
10690 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 11028 {
10691 res.Add(new LSL_Integer((uint)texgen >> 1)); 11029 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
11030 }
11031 else
11032 {
11033 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
11034 }
10692 } 11035 }
10693 } 11036 }
10694 else 11037 else
10695 { 11038 {
10696 if (face >= 0 && face < GetNumberOfSides(part)) 11039 if (tex.GetFace((uint)face).TexMapType == MappingType.Planar)
10697 { 11040 {
10698 MappingType texgen = tex.GetFace((uint)face).TexMapType; 11041 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR));
10699 res.Add(new LSL_Integer((uint)texgen >> 1)); 11042 }
11043 else
11044 {
11045 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
10700 } 11046 }
10701 } 11047 }
10702 break; 11048 break;
@@ -10720,24 +11066,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10720 if (remain < 1) 11066 if (remain < 1)
10721 return new LSL_List(); 11067 return new LSL_List();
10722 11068
10723 face=(int)rules.GetLSLIntegerItem(idx++); 11069 face = (int)rules.GetLSLIntegerItem(idx++);
10724 11070
10725 tex = part.Shape.Textures; 11071 tex = part.Shape.Textures;
11072 float primglow;
10726 if (face == ScriptBaseClass.ALL_SIDES) 11073 if (face == ScriptBaseClass.ALL_SIDES)
10727 { 11074 {
10728 for (face = 0; face < GetNumberOfSides(part); face++) 11075 for (face = 0; face < GetNumberOfSides(part); face++)
10729 { 11076 {
10730 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 11077 primglow = tex.GetFace((uint)face).Glow;
10731 res.Add(new LSL_Float(texface.Glow)); 11078 res.Add(new LSL_Float(primglow));
10732 } 11079 }
10733 } 11080 }
10734 else 11081 else
10735 { 11082 {
10736 if (face >= 0 && face < GetNumberOfSides(part)) 11083 primglow = tex.GetFace((uint)face).Glow;
10737 { 11084 res.Add(new LSL_Float(primglow));
10738 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10739 res.Add(new LSL_Float(texface.Glow));
10740 }
10741 } 11085 }
10742 break; 11086 break;
10743 11087
@@ -10747,17 +11091,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10747 res.Add(new LSL_Vector(textColor.R, 11091 res.Add(new LSL_Vector(textColor.R,
10748 textColor.G, 11092 textColor.G,
10749 textColor.B)); 11093 textColor.B));
10750 res.Add(new LSL_Float(1.0 - textColor.A)); 11094 res.Add(new LSL_Float(textColor.A));
10751 break; 11095 break;
11096
10752 case (int)ScriptBaseClass.PRIM_NAME: 11097 case (int)ScriptBaseClass.PRIM_NAME:
10753 res.Add(new LSL_String(part.Name)); 11098 res.Add(new LSL_String(part.Name));
10754 break; 11099 break;
11100
10755 case (int)ScriptBaseClass.PRIM_DESC: 11101 case (int)ScriptBaseClass.PRIM_DESC:
10756 res.Add(new LSL_String(part.Description)); 11102 res.Add(new LSL_String(part.Description));
10757 break; 11103 break;
10758 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 11104 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
10759 res.Add(new LSL_Rotation(part.RotationOffset)); 11105 res.Add(new LSL_Rotation(part.RotationOffset));
10760 break; 11106 break;
11107
10761 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 11108 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
10762 res.Add(new LSL_Vector(GetPartLocalPos(part))); 11109 res.Add(new LSL_Vector(GetPartLocalPos(part)));
10763 break; 11110 break;
@@ -10783,6 +11130,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10783 return new LSL_List(); 11130 return new LSL_List();
10784 } 11131 }
10785 11132
11133
10786 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 11134 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
10787 { 11135 {
10788 m_host.AddScriptLPS(1); 11136 m_host.AddScriptLPS(1);
@@ -11370,8 +11718,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11370 // The function returns an ordered list 11718 // The function returns an ordered list
11371 // representing the tokens found in the supplied 11719 // representing the tokens found in the supplied
11372 // sources string. If two successive tokenizers 11720 // sources string. If two successive tokenizers
11373 // are encountered, then a NULL entry is added 11721 // are encountered, then a null-string entry is
11374 // to the list. 11722 // added to the list.
11375 // 11723 //
11376 // It is a precondition that the source and 11724 // It is a precondition that the source and
11377 // toekizer lisst are non-null. If they are null, 11725 // toekizer lisst are non-null. If they are null,
@@ -11379,7 +11727,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11379 // while their lengths are being determined. 11727 // while their lengths are being determined.
11380 // 11728 //
11381 // A small amount of working memoryis required 11729 // A small amount of working memoryis required
11382 // of approximately 8*#tokenizers. 11730 // of approximately 8*#tokenizers + 8*srcstrlen.
11383 // 11731 //
11384 // There are many ways in which this function 11732 // There are many ways in which this function
11385 // can be implemented, this implementation is 11733 // can be implemented, this implementation is
@@ -11395,155 +11743,124 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11395 // and eliminates redundant tokenizers as soon 11743 // and eliminates redundant tokenizers as soon
11396 // as is possible. 11744 // as is possible.
11397 // 11745 //
11398 // The implementation tries to avoid any copying 11746 // The implementation tries to minimize temporary
11399 // of arrays or other objects. 11747 // garbage generation.
11400 // </remarks> 11748 // </remarks>
11401 11749
11402 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 11750 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
11403 { 11751 {
11404 int beginning = 0; 11752 return ParseString2List(src, separators, spacers, true);
11405 int srclen = src.Length; 11753 }
11406 int seplen = separators.Length;
11407 object[] separray = separators.Data;
11408 int spclen = spacers.Length;
11409 object[] spcarray = spacers.Data;
11410 int mlen = seplen+spclen;
11411
11412 int[] offset = new int[mlen+1];
11413 bool[] active = new bool[mlen];
11414
11415 int best;
11416 int j;
11417
11418 // Initial capacity reduces resize cost
11419 11754
11420 LSL_List tokens = new LSL_List(); 11755 private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
11756 {
11757 int srclen = src.Length;
11758 int seplen = separators.Length;
11759 object[] separray = separators.Data;
11760 int spclen = spacers.Length;
11761 object[] spcarray = spacers.Data;
11762 int dellen = 0;
11763 string[] delarray = new string[seplen+spclen];
11421 11764
11422 // All entries are initially valid 11765 int outlen = 0;
11766 string[] outarray = new string[srclen*2+1];
11423 11767
11424 for (int i = 0; i < mlen; i++) 11768 int i, j;
11425 active[i] = true; 11769 string d;
11426 11770
11427 offset[mlen] = srclen; 11771 m_host.AddScriptLPS(1);
11428 11772
11429 while (beginning < srclen) 11773 /*
11774 * Convert separator and spacer lists to C# strings.
11775 * Also filter out null strings so we don't hang.
11776 */
11777 for (i = 0; i < seplen; i ++)
11430 { 11778 {
11779 d = separray[i].ToString();
11780 if (d.Length > 0)
11781 {
11782 delarray[dellen++] = d;
11783 }
11784 }
11785 seplen = dellen;
11431 11786
11432 best = mlen; // as bad as it gets 11787 for (i = 0; i < spclen; i ++)
11788 {
11789 d = spcarray[i].ToString();
11790 if (d.Length > 0)
11791 {
11792 delarray[dellen++] = d;
11793 }
11794 }
11433 11795
11434 // Scan for separators 11796 /*
11797 * Scan through source string from beginning to end.
11798 */
11799 for (i = 0;;)
11800 {
11435 11801
11436 for (j = 0; j < seplen; j++) 11802 /*
11803 * Find earliest delimeter in src starting at i (if any).
11804 */
11805 int earliestDel = -1;
11806 int earliestSrc = srclen;
11807 string earliestStr = null;
11808 for (j = 0; j < dellen; j ++)
11437 { 11809 {
11438 if (separray[j].ToString() == String.Empty) 11810 d = delarray[j];
11439 active[j] = false; 11811 if (d != null)
11440
11441 if (active[j])
11442 { 11812 {
11443 // scan all of the markers 11813 int index = src.IndexOf(d, i);
11444 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 11814 if (index < 0)
11445 { 11815 {
11446 // not present at all 11816 delarray[j] = null; // delim nowhere in src, don't check it anymore
11447 active[j] = false;
11448 } 11817 }
11449 else 11818 else if (index < earliestSrc)
11450 { 11819 {
11451 // present and correct 11820 earliestSrc = index; // where delimeter starts in source string
11452 if (offset[j] < offset[best]) 11821 earliestDel = j; // where delimeter is in delarray[]
11453 { 11822 earliestStr = d; // the delimeter string from delarray[]
11454 // closest so far 11823 if (index == i) break; // can't do any better than found at beg of string
11455 best = j;
11456 if (offset[best] == beginning)
11457 break;
11458 }
11459 } 11824 }
11460 } 11825 }
11461 } 11826 }
11462 11827
11463 // Scan for spacers 11828 /*
11464 11829 * Output source string starting at i through start of earliest delimeter.
11465 if (offset[best] != beginning) 11830 */
11831 if (keepNulls || (earliestSrc > i))
11466 { 11832 {
11467 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 11833 outarray[outlen++] = src.Substring(i, earliestSrc - i);
11468 {
11469 if (spcarray[j-seplen].ToString() == String.Empty)
11470 active[j] = false;
11471
11472 if (active[j])
11473 {
11474 // scan all of the markers
11475 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
11476 {
11477 // not present at all
11478 active[j] = false;
11479 }
11480 else
11481 {
11482 // present and correct
11483 if (offset[j] < offset[best])
11484 {
11485 // closest so far
11486 best = j;
11487 }
11488 }
11489 }
11490 }
11491 } 11834 }
11492 11835
11493 // This is the normal exit from the scanning loop 11836 /*
11837 * If no delimeter found at or after i, we're done scanning.
11838 */
11839 if (earliestDel < 0) break;
11494 11840
11495 if (best == mlen) 11841 /*
11842 * If delimeter was a spacer, output the spacer.
11843 */
11844 if (earliestDel >= seplen)
11496 { 11845 {
11497 // no markers were found on this pass 11846 outarray[outlen++] = earliestStr;
11498 // so we're pretty much done
11499 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
11500 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
11501 break;
11502 } 11847 }
11503 11848
11504 // Otherwise we just add the newly delimited token 11849 /*
11505 // and recalculate where the search should continue. 11850 * Look at rest of src string following delimeter.
11506 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 11851 */
11507 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 11852 i = earliestSrc + earliestStr.Length;
11508
11509 if (best < seplen)
11510 {
11511 beginning = offset[best] + (separray[best].ToString()).Length;
11512 }
11513 else
11514 {
11515 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
11516 string str = spcarray[best - seplen].ToString();
11517 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
11518 tokens.Add(new LSL_String(str));
11519 }
11520 } 11853 }
11521 11854
11522 // This an awkward an not very intuitive boundary case. If the 11855 /*
11523 // last substring is a tokenizer, then there is an implied trailing 11856 * Make up an exact-sized output array suitable for an LSL_List object.
11524 // null list entry. Hopefully the single comparison will not be too 11857 */
11525 // arduous. Alternatively the 'break' could be replced with a return 11858 object[] outlist = new object[outlen];
11526 // but that's shabby programming. 11859 for (i = 0; i < outlen; i ++)
11527
11528 if ((beginning == srclen) && (keepNulls))
11529 { 11860 {
11530 if (srclen != 0) 11861 outlist[i] = new LSL_String(outarray[i]);
11531 tokens.Add(new LSL_String(""));
11532 } 11862 }
11533 11863 return new LSL_List(outlist);
11534 return tokens;
11535 }
11536
11537 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
11538 {
11539 m_host.AddScriptLPS(1);
11540 return this.ParseString(src, separators, spacers, false);
11541 }
11542
11543 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
11544 {
11545 m_host.AddScriptLPS(1);
11546 return this.ParseString(src, separators, spacers, true);
11547 } 11864 }
11548 11865
11549 public LSL_Integer llGetObjectPermMask(int mask) 11866 public LSL_Integer llGetObjectPermMask(int mask)
@@ -11841,31 +12158,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11841 UUID key = new UUID(); 12158 UUID key = new UUID();
11842 if (UUID.TryParse(id, out key)) 12159 if (UUID.TryParse(id, out key))
11843 { 12160 {
11844 try 12161 // return total object mass
11845 { 12162 SceneObjectPart part = World.GetSceneObjectPart(key);
11846 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 12163 if (part != null)
11847 if (obj != null) 12164 return part.ParentGroup.GetMass();
11848 return (double)obj.GetMass(); 12165
11849 // the object is null so the key is for an avatar 12166 // the object is null so the key is for an avatar
11850 ScenePresence avatar = World.GetScenePresence(key); 12167 ScenePresence avatar = World.GetScenePresence(key);
11851 if (avatar != null) 12168 if (avatar != null)
11852 if (avatar.IsChildAgent)
11853 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
11854 // child agents have a mass of 1.0
11855 return 1;
11856 else
11857 return (double)avatar.GetMass();
11858 }
11859 catch (KeyNotFoundException)
11860 { 12169 {
11861 return 0; // The Object/Agent not in the region so just return zero 12170 if (avatar.IsChildAgent)
12171 {
12172 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
12173 // child agents have a mass of 1.0
12174 return 1;
12175 }
12176 else
12177 {
12178 return (double)avatar.GetMass();
12179 }
11862 } 12180 }
11863 } 12181 }
11864 return 0; 12182 return 0;
11865 } 12183 }
11866 12184
11867 /// <summary> 12185 /// <summary>
11868 /// illListReplaceList removes the sub-list defined by the inclusive indices 12186 /// llListReplaceList removes the sub-list defined by the inclusive indices
11869 /// start and end and inserts the src list in its place. The inclusive 12187 /// start and end and inserts the src list in its place. The inclusive
11870 /// nature of the indices means that at least one element must be deleted 12188 /// nature of the indices means that at least one element must be deleted
11871 /// if the indices are within the bounds of the existing list. I.e. 2,2 12189 /// if the indices are within the bounds of the existing list. I.e. 2,2
@@ -11922,16 +12240,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11922 // based upon end. Note that if end exceeds the upper 12240 // based upon end. Note that if end exceeds the upper
11923 // bound in this case, the entire destination list 12241 // bound in this case, the entire destination list
11924 // is removed. 12242 // is removed.
11925 else 12243 else if (start == 0)
11926 { 12244 {
11927 if (end + 1 < dest.Length) 12245 if (end + 1 < dest.Length)
11928 {
11929 return src + dest.GetSublist(end + 1, -1); 12246 return src + dest.GetSublist(end + 1, -1);
11930 }
11931 else 12247 else
11932 {
11933 return src; 12248 return src;
11934 } 12249 }
12250 else // Start < 0
12251 {
12252 if (end + 1 < dest.Length)
12253 return dest.GetSublist(end + 1, -1);
12254 else
12255 return new LSL_List();
11935 } 12256 }
11936 } 12257 }
11937 // Finally, if start > end, we strip away a prefix and 12258 // Finally, if start > end, we strip away a prefix and
@@ -11968,7 +12289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11968 // according to the docs, this command only works if script owner and land owner are the same 12289 // according to the docs, this command only works if script owner and land owner are the same
11969 // lets add estate owners and gods, too, and use the generic permission check. 12290 // lets add estate owners and gods, too, and use the generic permission check.
11970 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 12291 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
11971 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; 12292 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia, false)) return;
11972 12293
11973 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? 12294 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
11974 byte loop = 0; 12295 byte loop = 0;
@@ -12186,16 +12507,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12186 if (sp.currentParcelUUID == landData.GlobalID) 12507 if (sp.currentParcelUUID == landData.GlobalID)
12187 { 12508 {
12188 sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? 12509 sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
12189 (ParcelMediaCommandEnum)commandToSend, 12510 (ParcelMediaCommandEnum)commandToSend, time);
12190 time);
12191 } 12511 }
12192 }); 12512 });
12193 } 12513 }
12194 else if (!presence.IsChildAgent) 12514 else if (!presence.IsChildAgent)
12195 { 12515 {
12196 presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? 12516 presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
12197 (ParcelMediaCommandEnum)commandToSend, 12517 (ParcelMediaCommandEnum)commandToSend, time);
12198 time);
12199 } 12518 }
12200 } 12519 }
12201 ScriptSleep(m_sleepMsOnParcelMediaCommandList); 12520 ScriptSleep(m_sleepMsOnParcelMediaCommandList);
@@ -12212,7 +12531,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12212 12531
12213 if (aList.Data[i] != null) 12532 if (aList.Data[i] != null)
12214 { 12533 {
12215 switch ((ParcelMediaCommandEnum) aList.Data[i]) 12534 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
12216 { 12535 {
12217 case ParcelMediaCommandEnum.Url: 12536 case ParcelMediaCommandEnum.Url:
12218 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); 12537 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
@@ -12269,15 +12588,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12269 12588
12270 if (quick_pay_buttons.Data.Length < 4) 12589 if (quick_pay_buttons.Data.Length < 4)
12271 { 12590 {
12272 Error("llSetPayPrice", "List must have at least 4 elements"); 12591 int x;
12273 return; 12592 for (x=quick_pay_buttons.Data.Length; x<= 4; x++)
12593 {
12594 quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE);
12595 }
12274 } 12596 }
12275 m_host.ParentGroup.RootPart.PayPrice[0]=price; 12597 int[] nPrice = new int[5];
12276 12598 nPrice[0] = price;
12277 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 12599 nPrice[1] = quick_pay_buttons.GetLSLIntegerItem(0);
12278 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 12600 nPrice[2] = quick_pay_buttons.GetLSLIntegerItem(1);
12279 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 12601 nPrice[3] = quick_pay_buttons.GetLSLIntegerItem(2);
12280 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 12602 nPrice[4] = quick_pay_buttons.GetLSLIntegerItem(3);
12603 m_host.ParentGroup.RootPart.PayPrice = nPrice;
12281 m_host.ParentGroup.HasGroupChanged = true; 12604 m_host.ParentGroup.HasGroupChanged = true;
12282 } 12605 }
12283 12606
@@ -12294,7 +12617,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12294 return Vector3.Zero; 12617 return Vector3.Zero;
12295 } 12618 }
12296 12619
12297 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 12620// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
12621 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
12298 if (presence != null) 12622 if (presence != null)
12299 { 12623 {
12300 LSL_Vector pos = new LSL_Vector(presence.CameraPosition); 12624 LSL_Vector pos = new LSL_Vector(presence.CameraPosition);
@@ -12317,7 +12641,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12317 return Quaternion.Identity; 12641 return Quaternion.Identity;
12318 } 12642 }
12319 12643
12320 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 12644// ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
12645 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
12321 if (presence != null) 12646 if (presence != null)
12322 { 12647 {
12323 return new LSL_Rotation(presence.CameraRotation); 12648 return new LSL_Rotation(presence.CameraRotation);
@@ -12370,8 +12695,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12370 { 12695 {
12371 m_host.AddScriptLPS(1); 12696 m_host.AddScriptLPS(1);
12372 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 12697 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
12373 if (detectedParams == null) return; // only works on the first detected avatar 12698 if (detectedParams == null)
12374 12699 {
12700 if (m_host.ParentGroup.IsAttachment == true)
12701 {
12702 detectedParams = new DetectParams();
12703 detectedParams.Key = m_host.OwnerID;
12704 }
12705 else
12706 {
12707 return;
12708 }
12709 }
12710
12375 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 12711 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
12376 if (avatar != null) 12712 if (avatar != null)
12377 { 12713 {
@@ -12386,7 +12722,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12386 m_host.AddScriptLPS(1); 12722 m_host.AddScriptLPS(1);
12387 UUID key; 12723 UUID key;
12388 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 12724 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12389 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 12725 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
12390 { 12726 {
12391 int expires = 0; 12727 int expires = 0;
12392 if (hours != 0) 12728 if (hours != 0)
@@ -12427,7 +12763,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12427 m_host.AddScriptLPS(1); 12763 m_host.AddScriptLPS(1);
12428 UUID key; 12764 UUID key;
12429 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 12765 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12430 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) 12766 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed, false))
12431 { 12767 {
12432 if (UUID.TryParse(avatar, out key)) 12768 if (UUID.TryParse(avatar, out key))
12433 { 12769 {
@@ -12454,7 +12790,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12454 m_host.AddScriptLPS(1); 12790 m_host.AddScriptLPS(1);
12455 UUID key; 12791 UUID key;
12456 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 12792 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12457 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 12793 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false))
12458 { 12794 {
12459 if (UUID.TryParse(avatar, out key)) 12795 if (UUID.TryParse(avatar, out key))
12460 { 12796 {
@@ -12686,19 +13022,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12686 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 13022 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
12687 { 13023 {
12688 m_host.AddScriptLPS(1); 13024 m_host.AddScriptLPS(1);
12689 string ret = String.Empty; 13025
12690 string src1 = llBase64ToString(str1); 13026 if (str1 == String.Empty)
12691 string src2 = llBase64ToString(str2); 13027 return String.Empty;
12692 int c = 0; 13028 if (str2 == String.Empty)
12693 for (int i = 0; i < src1.Length; i++) 13029 return str1;
13030
13031 int len = str2.Length;
13032 if ((len % 4) != 0) // LL is EVIL!!!!
13033 {
13034 while (str2.EndsWith("="))
13035 str2 = str2.Substring(0, str2.Length - 1);
13036
13037 len = str2.Length;
13038 int mod = len % 4;
13039
13040 if (mod == 1)
13041 str2 = str2.Substring(0, str2.Length - 1);
13042 else if (mod == 2)
13043 str2 += "==";
13044 else if (mod == 3)
13045 str2 += "=";
13046 }
13047
13048 byte[] data1;
13049 byte[] data2;
13050 try
12694 { 13051 {
12695 ret += (char) (src1[i] ^ src2[c]); 13052 data1 = Convert.FromBase64String(str1);
13053 data2 = Convert.FromBase64String(str2);
13054 }
13055 catch (Exception)
13056 {
13057 return new LSL_String(String.Empty);
13058 }
12696 13059
12697 c++; 13060 byte[] d2 = new Byte[data1.Length];
12698 if (c >= src2.Length) 13061 int pos = 0;
12699 c = 0; 13062
13063 if (data1.Length <= data2.Length)
13064 {
13065 Array.Copy(data2, 0, d2, 0, data1.Length);
12700 } 13066 }
12701 return llStringToBase64(ret); 13067 else
13068 {
13069 while (pos < data1.Length)
13070 {
13071 len = data1.Length - pos;
13072 if (len > data2.Length)
13073 len = data2.Length;
13074
13075 Array.Copy(data2, 0, d2, pos, len);
13076 pos += len;
13077 }
13078 }
13079
13080 for (pos = 0 ; pos < data1.Length ; pos++ )
13081 data1[pos] ^= d2[pos];
13082
13083 return Convert.ToBase64String(data1);
12702 } 13084 }
12703 13085
12704 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 13086 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
@@ -12802,16 +13184,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12802 if (userAgent != null) 13184 if (userAgent != null)
12803 httpHeaders["User-Agent"] = userAgent; 13185 httpHeaders["User-Agent"] = userAgent;
12804 13186
13187 // See if the URL contains any header hacks
13188 string[] urlParts = url.Split(new char[] {'\n'});
13189 if (urlParts.Length > 1)
13190 {
13191 // Iterate the passed headers and parse them
13192 for (int i = 1 ; i < urlParts.Length ; i++ )
13193 {
13194 // The rest of those would be added to the body in SL.
13195 // Let's not do that.
13196 if (urlParts[i] == String.Empty)
13197 break;
13198
13199 // See if this could be a valid header
13200 string[] headerParts = urlParts[i].Split(new char[] {':'}, 2);
13201 if (headerParts.Length != 2)
13202 continue;
13203
13204 string headerName = headerParts[0].Trim();
13205 string headerValue = headerParts[1].Trim();
13206
13207 // Filter out headers that could be used to abuse
13208 // another system or cloak the request
13209 if (headerName.ToLower() == "x-secondlife-shard" ||
13210 headerName.ToLower() == "x-secondlife-object-name" ||
13211 headerName.ToLower() == "x-secondlife-object-key" ||
13212 headerName.ToLower() == "x-secondlife-region" ||
13213 headerName.ToLower() == "x-secondlife-local-position" ||
13214 headerName.ToLower() == "x-secondlife-local-velocity" ||
13215 headerName.ToLower() == "x-secondlife-local-rotation" ||
13216 headerName.ToLower() == "x-secondlife-owner-name" ||
13217 headerName.ToLower() == "x-secondlife-owner-key" ||
13218 headerName.ToLower() == "connection" ||
13219 headerName.ToLower() == "content-length" ||
13220 headerName.ToLower() == "from" ||
13221 headerName.ToLower() == "host" ||
13222 headerName.ToLower() == "proxy-authorization" ||
13223 headerName.ToLower() == "referer" ||
13224 headerName.ToLower() == "trailer" ||
13225 headerName.ToLower() == "transfer-encoding" ||
13226 headerName.ToLower() == "via" ||
13227 headerName.ToLower() == "authorization")
13228 continue;
13229
13230 httpHeaders[headerName] = headerValue;
13231 }
13232
13233 // Finally, strip any protocol specifier from the URL
13234 url = urlParts[0].Trim();
13235 int idx = url.IndexOf(" HTTP/");
13236 if (idx != -1)
13237 url = url.Substring(0, idx);
13238 }
13239
12805 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; 13240 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
12806 Regex r = new Regex(authregex); 13241 Regex r = new Regex(authregex);
12807 int[] gnums = r.GetGroupNumbers(); 13242 int[] gnums = r.GetGroupNumbers();
12808 Match m = r.Match(url); 13243 Match m = r.Match(url);
12809 if (m.Success) { 13244 if (m.Success)
12810 for (int i = 1; i < gnums.Length; i++) { 13245 {
13246 for (int i = 1; i < gnums.Length; i++)
13247 {
12811 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 13248 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
12812 //CaptureCollection cc = g.Captures; 13249 //CaptureCollection cc = g.Captures;
12813 } 13250 }
12814 if (m.Groups.Count == 5) { 13251 if (m.Groups.Count == 5)
13252 {
12815 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 13253 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
12816 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 13254 url = m.Groups[1].ToString() + m.Groups[4].ToString();
12817 } 13255 }
@@ -13018,6 +13456,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13018 13456
13019 LSL_List ret = new LSL_List(); 13457 LSL_List ret = new LSL_List();
13020 UUID key = new UUID(); 13458 UUID key = new UUID();
13459
13460
13021 if (UUID.TryParse(id, out key)) 13461 if (UUID.TryParse(id, out key))
13022 { 13462 {
13023 ScenePresence av = World.GetScenePresence(key); 13463 ScenePresence av = World.GetScenePresence(key);
@@ -13035,13 +13475,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13035 ret.Add(new LSL_String("")); 13475 ret.Add(new LSL_String(""));
13036 break; 13476 break;
13037 case ScriptBaseClass.OBJECT_POS: 13477 case ScriptBaseClass.OBJECT_POS:
13038 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 13478 Vector3 avpos;
13479
13480 if (av.ParentID != 0 && av.ParentPart != null &&
13481 av.ParentPart.ParentGroup != null && av.ParentPart.ParentGroup.RootPart != null )
13482 {
13483 avpos = av.OffsetPosition;
13484
13485 Vector3 sitOffset = (Zrot(av.Rotation)) * (av.Appearance.AvatarHeight * 0.02638f *2.0f);
13486 avpos -= sitOffset;
13487 SceneObjectPart sitRoot = av.ParentPart.ParentGroup.RootPart;
13488 avpos = sitRoot.GetWorldPosition() + avpos * sitRoot.GetWorldRotation();
13489 }
13490 else
13491 avpos = av.AbsolutePosition;
13492
13493 ret.Add(new LSL_Vector((double)avpos.X, (double)avpos.Y, (double)avpos.Z));
13039 break; 13494 break;
13040 case ScriptBaseClass.OBJECT_ROT: 13495 case ScriptBaseClass.OBJECT_ROT:
13041 ret.Add(new LSL_Rotation(av.GetWorldRotation())); 13496 Quaternion avrot = av.GetWorldRotation();
13497 ret.Add(new LSL_Rotation(avrot));
13042 break; 13498 break;
13043 case ScriptBaseClass.OBJECT_VELOCITY: 13499 case ScriptBaseClass.OBJECT_VELOCITY:
13044 ret.Add(new LSL_Vector(av.GetWorldVelocity())); 13500 Vector3 avvel = av.GetWorldVelocity();
13501 ret.Add(new LSL_Vector((double)avvel.X, (double)avvel.Y, (double)avvel.Z));
13045 break; 13502 break;
13046 case ScriptBaseClass.OBJECT_OWNER: 13503 case ScriptBaseClass.OBJECT_OWNER:
13047 ret.Add(new LSL_String(id)); 13504 ret.Add(new LSL_String(id));
@@ -13143,11 +13600,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13143 case ScriptBaseClass.OBJECT_NAME: 13600 case ScriptBaseClass.OBJECT_NAME:
13144 ret.Add(new LSL_String(obj.Name)); 13601 ret.Add(new LSL_String(obj.Name));
13145 break; 13602 break;
13146 case ScriptBaseClass.OBJECT_DESC: 13603 case ScriptBaseClass.OBJECT_DESC:
13147 ret.Add(new LSL_String(obj.Description)); 13604 ret.Add(new LSL_String(obj.Description));
13148 break; 13605 break;
13149 case ScriptBaseClass.OBJECT_POS: 13606 case ScriptBaseClass.OBJECT_POS:
13150 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 13607 Vector3 opos = obj.AbsolutePosition;
13608 ret.Add(new LSL_Vector(opos.X, opos.Y, opos.Z));
13151 break; 13609 break;
13152 case ScriptBaseClass.OBJECT_ROT: 13610 case ScriptBaseClass.OBJECT_ROT:
13153 Quaternion rot = Quaternion.Identity; 13611 Quaternion rot = Quaternion.Identity;
@@ -13220,9 +13678,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13220 // The value returned in SL for normal prims is prim count 13678 // The value returned in SL for normal prims is prim count
13221 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 13679 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
13222 break; 13680 break;
13223 // The following 3 costs I have intentionaly coded to return zero. They are part of 13681
13224 // "Land Impact" calculations. These calculations are probably not applicable 13682 // costs below may need to be diferent for root parts, need to check
13225 // to OpenSim and are not yet complete in SL
13226 case ScriptBaseClass.OBJECT_SERVER_COST: 13683 case ScriptBaseClass.OBJECT_SERVER_COST:
13227 // The linden calculation is here 13684 // The linden calculation is here
13228 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 13685 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
@@ -13230,16 +13687,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13230 ret.Add(new LSL_Float(0)); 13687 ret.Add(new LSL_Float(0));
13231 break; 13688 break;
13232 case ScriptBaseClass.OBJECT_STREAMING_COST: 13689 case ScriptBaseClass.OBJECT_STREAMING_COST:
13233 // The linden calculation is here 13690 // The value returned in SL for normal prims is prim count * 0.06
13234 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 13691 ret.Add(new LSL_Float(obj.StreamingCost));
13235 // The value returned in SL for normal prims looks like the prim count * 0.06
13236 ret.Add(new LSL_Float(0));
13237 break; 13692 break;
13238 case ScriptBaseClass.OBJECT_PHYSICS_COST: 13693 case ScriptBaseClass.OBJECT_PHYSICS_COST:
13239 // The linden calculation is here 13694 // The value returned in SL for normal prims is prim count
13240 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 13695 ret.Add(new LSL_Float(obj.PhysicsCost));
13241 // The value returned in SL for normal prims looks like the prim count
13242 ret.Add(new LSL_Float(0));
13243 break; 13696 break;
13244 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding 13697 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
13245 ret.Add(new LSL_Float(0)); 13698 ret.Add(new LSL_Float(0));
@@ -13522,12 +13975,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13522 13975
13523 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 13976 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
13524 { 13977 {
13525 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 13978 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
13979
13980 LSL_List result = new LSL_List();
13526 13981
13527 if (obj != null && obj.OwnerID == m_host.OwnerID) 13982 if (obj != null && obj.OwnerID == m_host.OwnerID)
13528 return GetEntityParams(obj, rules); 13983 {
13984 LSL_List remaining = GetPrimParams(obj, rules, ref result);
13529 13985
13530 return new LSL_List(); 13986 while (remaining.Length > 2)
13987 {
13988 int linknumber = remaining.GetLSLIntegerItem(0);
13989 rules = remaining.GetSublist(1, -1);
13990 List<SceneObjectPart> parts = GetLinkParts(linknumber);
13991
13992 foreach (SceneObjectPart part in parts)
13993 remaining = GetPrimParams(part, rules, ref result);
13994 }
13995 }
13996
13997 return result;
13531 } 13998 }
13532 13999
13533 public void print(string str) 14000 public void print(string str)
@@ -13539,6 +14006,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13539 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 14006 ossl.CheckThreatLevel(ThreatLevel.High, "print");
13540 m_log.Info("LSL print():" + str); 14007 m_log.Info("LSL print():" + str);
13541 } 14008 }
14009 }
14010
14011 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
14012 {
14013 List<SceneObjectPart> parts = GetLinkParts(link);
14014 if (parts.Count < 1)
14015 return 0;
14016
14017 return GetNumberOfSides(parts[0]);
13542 } 14018 }
13543 14019
13544 private string Name2Username(string name) 14020 private string Name2Username(string name)
@@ -13583,7 +14059,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13583 14059
13584 return rq.ToString(); 14060 return rq.ToString();
13585 } 14061 }
13586 14062/*
14063 private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args)
14064 {
14065 m_SayShoutCount = 0;
14066 }
14067*/
13587 private struct Tri 14068 private struct Tri
13588 { 14069 {
13589 public Vector3 p1; 14070 public Vector3 p1;
@@ -13732,9 +14213,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13732 14213
13733 ContactResult result = new ContactResult (); 14214 ContactResult result = new ContactResult ();
13734 result.ConsumerID = group.LocalId; 14215 result.ConsumerID = group.LocalId;
13735 result.Depth = intersection.distance; 14216// result.Depth = intersection.distance;
13736 result.Normal = intersection.normal; 14217 result.Normal = intersection.normal;
13737 result.Pos = intersection.ipoint; 14218 result.Pos = intersection.ipoint;
14219 result.Depth = Vector3.Mag(rayStart - result.Pos);
13738 14220
13739 contacts.Add(result); 14221 contacts.Add(result);
13740 }); 14222 });
@@ -13867,6 +14349,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13867 14349
13868 return contacts[0]; 14350 return contacts[0];
13869 } 14351 }
14352/*
14353 // not done:
14354 private ContactResult[] testRay2NonPhysicalPhantom(Vector3 rayStart, Vector3 raydir, float raylenght)
14355 {
14356 ContactResult[] contacts = null;
14357 World.ForEachSOG(delegate(SceneObjectGroup group)
14358 {
14359 if (m_host.ParentGroup == group)
14360 return;
14361
14362 if (group.IsAttachment)
14363 return;
14364
14365 if(group.RootPart.PhysActor != null)
14366 return;
14367
14368 contacts = group.RayCastGroupPartsOBBNonPhysicalPhantom(rayStart, raydir, raylenght);
14369 });
14370 return contacts;
14371 }
14372*/
13870 14373
13871 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 14374 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
13872 { 14375 {
@@ -13917,7 +14420,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13917 if (dist == 0) 14420 if (dist == 0)
13918 return list; 14421 return list;
13919 14422
13920 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull; 14423 RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
13921 if (checkTerrain) 14424 if (checkTerrain)
13922 rayfilter |= RayFilterFlags.land; 14425 rayfilter |= RayFilterFlags.land;
13923// if (checkAgents) 14426// if (checkAgents)
@@ -13994,18 +14497,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13994 } 14497 }
13995 } 14498 }
13996 14499
14500 // Double check this
13997 if (checkTerrain) 14501 if (checkTerrain)
13998 { 14502 {
13999 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 14503 bool skipGroundCheck = false;
14000 if (groundContact != null) 14504
14001 results.Add((ContactResult)groundContact); 14505 foreach (ContactResult c in results)
14506 {
14507 if (c.ConsumerID == 0) // Physics gave us a ground collision
14508 skipGroundCheck = true;
14509 }
14510
14511 if (!skipGroundCheck)
14512 {
14513 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
14514 if (groundContact != null)
14515 results.Add((ContactResult)groundContact);
14516 }
14002 } 14517 }
14003 14518
14004 results.Sort(delegate(ContactResult a, ContactResult b) 14519 results.Sort(delegate(ContactResult a, ContactResult b)
14005 { 14520 {
14006 return a.Depth.CompareTo(b.Depth); 14521 return a.Depth.CompareTo(b.Depth);
14007 }); 14522 });
14008 14523
14009 int values = 0; 14524 int values = 0;
14010 SceneObjectGroup thisgrp = m_host.ParentGroup; 14525 SceneObjectGroup thisgrp = m_host.ParentGroup;
14011 14526
@@ -14062,6 +14577,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14062 14577
14063 return list; 14578 return list;
14064 } 14579 }
14580
14065 14581
14066 /// <summary> 14582 /// <summary>
14067 /// Implementation of llCastRay similar to SL 2015-04-21. 14583 /// Implementation of llCastRay similar to SL 2015-04-21.
@@ -14086,7 +14602,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14086 UUID userId = UUID.Zero; 14602 UUID userId = UUID.Zero;
14087 int msAvailable = 0; 14603 int msAvailable = 0;
14088 // Throttle per owner when attachment or "vehicle" (sat upon) 14604 // Throttle per owner when attachment or "vehicle" (sat upon)
14089 if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0) 14605 if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatarsCount() > 0)
14090 { 14606 {
14091 userId = m_host.OwnerID; 14607 userId = m_host.OwnerID;
14092 msAvailable = m_msPerAvatarInCastRay; 14608 msAvailable = m_msPerAvatarInCastRay;
@@ -14964,7 +15480,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14964 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 15480 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
14965 if (!isAccount) return 0; 15481 if (!isAccount) return 0;
14966 if (estate.HasAccess(id)) return 1; 15482 if (estate.HasAccess(id)) return 1;
14967 if (estate.IsBanned(id)) 15483 if (estate.IsBanned(id, World.GetUserFlags(id)))
14968 estate.RemoveBan(id); 15484 estate.RemoveBan(id);
14969 estate.AddEstateUser(id); 15485 estate.AddEstateUser(id);
14970 break; 15486 break;
@@ -14983,14 +15499,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
14983 break; 15499 break;
14984 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 15500 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
14985 if (!isAccount) return 0; 15501 if (!isAccount) return 0;
14986 if (estate.IsBanned(id)) return 1; 15502 if (estate.IsBanned(id, World.GetUserFlags(id))) return 1;
14987 EstateBan ban = new EstateBan(); 15503 EstateBan ban = new EstateBan();
14988 ban.EstateID = estate.EstateID; 15504 ban.EstateID = estate.EstateID;
14989 ban.BannedUserID = id; 15505 ban.BannedUserID = id;
14990 estate.AddBan(ban); 15506 estate.AddBan(ban);
14991 break; 15507 break;
14992 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 15508 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
14993 if (!isAccount || !estate.IsBanned(id)) return 0; 15509 if (!isAccount || !estate.IsBanned(id, World.GetUserFlags(id))) return 0;
14994 estate.RemoveBan(id); 15510 estate.RemoveBan(id);
14995 break; 15511 break;
14996 default: return 0; 15512 default: return 0;
@@ -15049,13 +15565,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
15049 public void llCollisionSprite(string impact_sprite) 15565 public void llCollisionSprite(string impact_sprite)
15050 { 15566 {
15051 m_host.AddScriptLPS(1); 15567 m_host.AddScriptLPS(1);
15052 NotImplemented("llCollisionSprite"); 15568 // Viewer 2.0 broke this and it's likely LL has no intention
15569 // of fixing it. Therefore, letting this be a NOP seems appropriate.
15053 } 15570 }
15054 15571
15055 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 15572 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
15056 { 15573 {
15057 m_host.AddScriptLPS(1); 15574 m_host.AddScriptLPS(1);
15058 NotImplemented("llGodLikeRezObject"); 15575
15576 if (!World.Permissions.IsGod(m_host.OwnerID))
15577 NotImplemented("llGodLikeRezObject");
15578
15579 AssetBase rezAsset = World.AssetService.Get(inventory);
15580 if (rezAsset == null)
15581 {
15582 llSay(0, "Asset not found");
15583 return;
15584 }
15585
15586 SceneObjectGroup group = null;
15587
15588 try
15589 {
15590 string xmlData = Utils.BytesToString(rezAsset.Data);
15591 group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
15592 }
15593 catch
15594 {
15595 llSay(0, "Asset not found");
15596 return;
15597 }
15598
15599 if (group == null)
15600 {
15601 llSay(0, "Asset not found");
15602 return;
15603 }
15604
15605 group.RootPart.AttachPoint = group.RootPart.Shape.State;
15606 group.RootPart.AttachedPos = group.AbsolutePosition;
15607
15608 group.ResetIDs();
15609
15610 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
15611 World.AddNewSceneObject(group, true, llpos, Quaternion.Identity, Vector3.Zero);
15612 group.CreateScriptInstances(0, true, World.DefaultScriptEngine, 3);
15613 group.ScheduleGroupForFullUpdate();
15614
15615 // objects rezzed with this method are die_at_edge by default.
15616 group.RootPart.SetDieAtEdge(true);
15617
15618 group.ResumeScripts();
15619
15620 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
15621 "object_rez", new Object[] {
15622 new LSL_String(
15623 group.RootPart.UUID.ToString()) },
15624 new DetectParams[0]));
15059 } 15625 }
15060 15626
15061 public LSL_String llTransferLindenDollars(string destination, int amount) 15627 public LSL_String llTransferLindenDollars(string destination, int amount)
@@ -15106,8 +15672,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
15106 return; 15672 return;
15107 } 15673 }
15108 15674
15675 string reason;
15109 bool result = money.ObjectGiveMoney( 15676 bool result = money.ObjectGiveMoney(
15110 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 15677 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn, out reason);
15111 15678
15112 if (result) 15679 if (result)
15113 { 15680 {
@@ -15115,7 +15682,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
15115 return; 15682 return;
15116 } 15683 }
15117 15684
15118 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS"; 15685 replydata = reason;
15119 } 15686 }
15120 finally 15687 finally
15121 { 15688 {
@@ -15132,6 +15699,815 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
15132 } 15699 }
15133 15700
15134 #endregion 15701 #endregion
15702
15703
15704 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
15705 {
15706 //This is a special version of SetPrimParams to deal with avatars which are sitting on the linkset.
15707
15708 int idx = 0;
15709 int idxStart = 0;
15710
15711 bool positionChanged = false;
15712 try
15713 {
15714 while (idx < rules.Length)
15715 {
15716 ++rulesParsed;
15717 int code = rules.GetLSLIntegerItem(idx++);
15718
15719 int remain = rules.Length - idx;
15720 idxStart = idx;
15721
15722 switch (code)
15723 {
15724 case (int)ScriptBaseClass.PRIM_POSITION:
15725 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
15726 {
15727 if (remain < 1)
15728 return new LSL_List();
15729
15730 LSL_Vector v;
15731 v = rules.GetVector3Item(idx++);
15732
15733 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
15734
15735 v = v + 2 * sitOffset;
15736
15737 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
15738 positionChanged = true;
15739 }
15740 break;
15741
15742 case (int)ScriptBaseClass.PRIM_ROTATION:
15743 {
15744 if (remain < 1)
15745 return new LSL_List();
15746
15747 Quaternion r;
15748 r = rules.GetQuaternionItem(idx++);
15749
15750 av.Rotation = m_host.GetWorldRotation() * r;
15751 positionChanged = true;
15752 }
15753 break;
15754
15755 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
15756 {
15757 if (remain < 1)
15758 return new LSL_List();
15759
15760 LSL_Rotation r;
15761 r = rules.GetQuaternionItem(idx++);
15762
15763 av.Rotation = r;
15764 positionChanged = true;
15765 }
15766 break;
15767
15768 // parse rest doing nothing but number of parameters error check
15769 case (int)ScriptBaseClass.PRIM_SIZE:
15770 case (int)ScriptBaseClass.PRIM_MATERIAL:
15771 case (int)ScriptBaseClass.PRIM_PHANTOM:
15772 case (int)ScriptBaseClass.PRIM_PHYSICS:
15773 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
15774 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
15775 case (int)ScriptBaseClass.PRIM_NAME:
15776 case (int)ScriptBaseClass.PRIM_DESC:
15777 if (remain < 1)
15778 return new LSL_List();
15779 idx++;
15780 break;
15781
15782 case (int)ScriptBaseClass.PRIM_GLOW:
15783 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
15784 case (int)ScriptBaseClass.PRIM_TEXGEN:
15785 if (remain < 2)
15786 return new LSL_List();
15787 idx += 2;
15788 break;
15789
15790 case (int)ScriptBaseClass.PRIM_TYPE:
15791 if (remain < 3)
15792 return new LSL_List();
15793 code = (int)rules.GetLSLIntegerItem(idx++);
15794 remain = rules.Length - idx;
15795 switch (code)
15796 {
15797 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
15798 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
15799 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
15800 if (remain < 6)
15801 return new LSL_List();
15802 idx += 6;
15803 break;
15804
15805 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
15806 if (remain < 5)
15807 return new LSL_List();
15808 idx += 5;
15809 break;
15810
15811 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
15812 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
15813 case (int)ScriptBaseClass.PRIM_TYPE_RING:
15814 if (remain < 11)
15815 return new LSL_List();
15816 idx += 11;
15817 break;
15818
15819 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
15820 if (remain < 2)
15821 return new LSL_List();
15822 idx += 2;
15823 break;
15824 }
15825 break;
15826
15827 case (int)ScriptBaseClass.PRIM_COLOR:
15828 case (int)ScriptBaseClass.PRIM_TEXT:
15829 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
15830 case (int)ScriptBaseClass.PRIM_OMEGA:
15831 if (remain < 3)
15832 return new LSL_List();
15833 idx += 3;
15834 break;
15835
15836 case (int)ScriptBaseClass.PRIM_TEXTURE:
15837 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
15838 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
15839 if (remain < 5)
15840 return new LSL_List();
15841 idx += 5;
15842 break;
15843
15844 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
15845 if (remain < 7)
15846 return new LSL_List();
15847
15848 idx += 7;
15849 break;
15850
15851 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
15852 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
15853 return new LSL_List();
15854
15855 return rules.GetSublist(idx, -1);
15856 }
15857 }
15858 }
15859 catch (InvalidCastException e)
15860 {
15861 Error(originFunc,string.Format(
15862 " error running rule #{1}: arg #{2} ",
15863 rulesParsed, idx - idxStart) + e.Message);
15864 }
15865 finally
15866 {
15867 if (positionChanged)
15868 av.SendTerseUpdateToAllClients();
15869 }
15870 return new LSL_List();
15871 }
15872
15873 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
15874 {
15875 // avatars case
15876 // replies as SL wiki
15877
15878// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
15879 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
15880
15881 int idx = 0;
15882 while (idx < rules.Length)
15883 {
15884 int code = (int)rules.GetLSLIntegerItem(idx++);
15885 int remain = rules.Length - idx;
15886
15887 switch (code)
15888 {
15889 case (int)ScriptBaseClass.PRIM_MATERIAL:
15890 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
15891 break;
15892
15893 case (int)ScriptBaseClass.PRIM_PHYSICS:
15894 res.Add(new LSL_Integer(0));
15895 break;
15896
15897 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
15898 res.Add(new LSL_Integer(0));
15899 break;
15900
15901 case (int)ScriptBaseClass.PRIM_PHANTOM:
15902 res.Add(new LSL_Integer(0));
15903 break;
15904
15905 case (int)ScriptBaseClass.PRIM_POSITION:
15906 Vector3 pos;
15907
15908 if (sitPart.ParentGroup.RootPart != null)
15909 {
15910 pos = avatar.OffsetPosition;
15911
15912 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
15913 pos -= sitOffset;
15914
15915 SceneObjectPart sitroot = sitPart.ParentGroup.RootPart;
15916 pos = sitroot.AbsolutePosition + pos * sitroot.GetWorldRotation();
15917 }
15918 else
15919 pos = avatar.AbsolutePosition;
15920
15921 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
15922 break;
15923
15924 case (int)ScriptBaseClass.PRIM_SIZE:
15925 Vector3 s = avatar.Appearance.AvatarSize;
15926 res.Add(new LSL_Vector(s.X, s.Y, s.Z));
15927
15928 break;
15929
15930 case (int)ScriptBaseClass.PRIM_ROTATION:
15931 res.Add(new LSL_Rotation(avatar.GetWorldRotation()));
15932 break;
15933
15934 case (int)ScriptBaseClass.PRIM_TYPE:
15935 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
15936 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
15937 res.Add(new LSL_Vector(0f,1.0f,0f));
15938 res.Add(new LSL_Float(0.0f));
15939 res.Add(new LSL_Vector(0, 0, 0));
15940 res.Add(new LSL_Vector(1.0f,1.0f,0f));
15941 res.Add(new LSL_Vector(0, 0, 0));
15942 break;
15943
15944 case (int)ScriptBaseClass.PRIM_TEXTURE:
15945 if (remain < 1)
15946 return new LSL_List();
15947
15948 int face = (int)rules.GetLSLIntegerItem(idx++);
15949 if (face == ScriptBaseClass.ALL_SIDES)
15950 {
15951 for (face = 0; face < 21; face++)
15952 {
15953 res.Add(new LSL_String(""));
15954 res.Add(new LSL_Vector(0,0,0));
15955 res.Add(new LSL_Vector(0,0,0));
15956 res.Add(new LSL_Float(0.0));
15957 }
15958 }
15959 else
15960 {
15961 if (face >= 0 && face < 21)
15962 {
15963 res.Add(new LSL_String(""));
15964 res.Add(new LSL_Vector(0,0,0));
15965 res.Add(new LSL_Vector(0,0,0));
15966 res.Add(new LSL_Float(0.0));
15967 }
15968 }
15969 break;
15970
15971 case (int)ScriptBaseClass.PRIM_COLOR:
15972 if (remain < 1)
15973 return new LSL_List();
15974
15975 face = (int)rules.GetLSLIntegerItem(idx++);
15976
15977 if (face == ScriptBaseClass.ALL_SIDES)
15978 {
15979 for (face = 0; face < 21; face++)
15980 {
15981 res.Add(new LSL_Vector(0,0,0));
15982 res.Add(new LSL_Float(0));
15983 }
15984 }
15985 else
15986 {
15987 res.Add(new LSL_Vector(0,0,0));
15988 res.Add(new LSL_Float(0));
15989 }
15990 break;
15991
15992 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
15993 if (remain < 1)
15994 return new LSL_List();
15995 face = (int)rules.GetLSLIntegerItem(idx++);
15996
15997 if (face == ScriptBaseClass.ALL_SIDES)
15998 {
15999 for (face = 0; face < 21; face++)
16000 {
16001 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
16002 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
16003 }
16004 }
16005 else
16006 {
16007 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
16008 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
16009 }
16010 break;
16011
16012 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
16013 if (remain < 1)
16014 return new LSL_List();
16015 face = (int)rules.GetLSLIntegerItem(idx++);
16016
16017 if (face == ScriptBaseClass.ALL_SIDES)
16018 {
16019 for (face = 0; face < 21; face++)
16020 {
16021 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
16022 }
16023 }
16024 else
16025 {
16026 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
16027 }
16028 break;
16029
16030 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
16031 res.Add(new LSL_Integer(0));
16032 res.Add(new LSL_Integer(0));// softness
16033 res.Add(new LSL_Float(0.0f)); // gravity
16034 res.Add(new LSL_Float(0.0f)); // friction
16035 res.Add(new LSL_Float(0.0f)); // wind
16036 res.Add(new LSL_Float(0.0f)); // tension
16037 res.Add(new LSL_Vector(0f,0f,0f));
16038 break;
16039
16040 case (int)ScriptBaseClass.PRIM_TEXGEN:
16041 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
16042 if (remain < 1)
16043 return new LSL_List();
16044 face = (int)rules.GetLSLIntegerItem(idx++);
16045
16046 if (face == ScriptBaseClass.ALL_SIDES)
16047 {
16048 for (face = 0; face < 21; face++)
16049 {
16050 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
16051 }
16052 }
16053 else
16054 {
16055 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
16056 }
16057 break;
16058
16059 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
16060 res.Add(new LSL_Integer(0));
16061 res.Add(new LSL_Vector(0f,0f,0f));
16062 res.Add(new LSL_Float(0f)); // intensity
16063 res.Add(new LSL_Float(0f)); // radius
16064 res.Add(new LSL_Float(0f)); // falloff
16065 break;
16066
16067 case (int)ScriptBaseClass.PRIM_GLOW:
16068 if (remain < 1)
16069 return new LSL_List();
16070 face = (int)rules.GetLSLIntegerItem(idx++);
16071
16072 if (face == ScriptBaseClass.ALL_SIDES)
16073 {
16074 for (face = 0; face < 21; face++)
16075 {
16076 res.Add(new LSL_Float(0f));
16077 }
16078 }
16079 else
16080 {
16081 res.Add(new LSL_Float(0f));
16082 }
16083 break;
16084
16085 case (int)ScriptBaseClass.PRIM_TEXT:
16086 res.Add(new LSL_String(""));
16087 res.Add(new LSL_Vector(0f,0f,0f));
16088 res.Add(new LSL_Float(1.0f));
16089 break;
16090
16091 case (int)ScriptBaseClass.PRIM_NAME:
16092 res.Add(new LSL_String(avatar.Name));
16093 break;
16094
16095 case (int)ScriptBaseClass.PRIM_DESC:
16096 res.Add(new LSL_String(""));
16097 break;
16098
16099 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
16100 Quaternion lrot = avatar.Rotation;
16101 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
16102 break;
16103
16104 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
16105 Vector3 lpos = avatar.OffsetPosition;
16106 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
16107 lpos -= lsitOffset;
16108
16109 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
16110 break;
16111
16112 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
16113 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
16114 return new LSL_List();
16115
16116 return rules.GetSublist(idx, -1);
16117 }
16118 }
16119
16120 return new LSL_List();
16121 }
16122
16123 public void llSetAnimationOverride(LSL_String animState, LSL_String anim)
16124 {
16125 string state = String.Empty;
16126
16127 foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16128 {
16129 if (kvp.Value.ToLower() == ((string)animState).ToLower())
16130 {
16131 state = kvp.Key;
16132 break;
16133 }
16134 }
16135
16136 if (state == String.Empty)
16137 {
16138 llShout(ScriptBaseClass.DEBUG_CHANNEL, "Invalid animation state " + animState);
16139 return;
16140 }
16141
16142 if (m_item.PermsGranter == UUID.Zero)
16143 {
16144 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16145 return;
16146 }
16147
16148 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS) == 0)
16149 {
16150 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16151 return;
16152 }
16153
16154 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16155
16156 if (presence == null)
16157 return;
16158
16159 UUID animID;
16160
16161 animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
16162
16163 if (animID == UUID.Zero)
16164 {
16165 String animupper = ((string)anim).ToUpperInvariant();
16166 DefaultAvatarAnimations.AnimsUUID.TryGetValue(animupper, out animID);
16167 }
16168
16169 if (animID == UUID.Zero)
16170 {
16171 llShout(ScriptBaseClass.DEBUG_CHANNEL, "Animation not found");
16172 return;
16173 }
16174
16175 presence.SetAnimationOverride(state, animID);
16176 }
16177
16178 public void llResetAnimationOverride(LSL_String animState)
16179 {
16180 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16181 if (presence == null)
16182 return;
16183
16184 if (m_item.PermsGranter == UUID.Zero)
16185 {
16186 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16187 return;
16188 }
16189
16190 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS) == 0)
16191 {
16192 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16193 return;
16194 }
16195
16196 if (animState == "ALL")
16197 {
16198 presence.SetAnimationOverride("ALL", UUID.Zero);
16199 return;
16200 }
16201
16202 string state = String.Empty;
16203
16204 foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16205 {
16206 if (kvp.Value.ToLower() == ((string)animState).ToLower())
16207 {
16208 state = kvp.Key;
16209 break;
16210 }
16211 }
16212
16213 if (state == String.Empty)
16214 {
16215 return;
16216 }
16217
16218 presence.SetAnimationOverride(state, UUID.Zero);
16219 }
16220
16221 public LSL_String llGetAnimationOverride(LSL_String animState)
16222 {
16223 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
16224 if (presence == null)
16225 return String.Empty;
16226
16227 if (m_item.PermsGranter == UUID.Zero)
16228 {
16229 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16230 return String.Empty;
16231 }
16232
16233 if ((m_item.PermsMask & (ScriptBaseClass.PERMISSION_OVERRIDE_ANIMATIONS | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION)) == 0)
16234 {
16235 llShout(ScriptBaseClass.DEBUG_CHANNEL, "No permission to override animations");
16236 return String.Empty;
16237 }
16238
16239 string state = String.Empty;
16240
16241 foreach (KeyValuePair<string, string> kvp in MovementAnimationsForLSL)
16242 {
16243 if (kvp.Value.ToLower() == ((string)animState).ToLower())
16244 {
16245 state = kvp.Key;
16246 break;
16247 }
16248 }
16249
16250 if (state == String.Empty)
16251 {
16252 return String.Empty;
16253 }
16254
16255 UUID animID = presence.GetAnimationOverride(state);
16256 if (animID == UUID.Zero)
16257 return animState;
16258
16259 foreach (KeyValuePair<string, UUID> kvp in DefaultAvatarAnimations.AnimsUUID)
16260 {
16261 if (kvp.Value == animID)
16262 return kvp.Key.ToLower();
16263 }
16264
16265 foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems())
16266 {
16267 if (item.AssetID == animID)
16268 return item.Name;
16269 }
16270
16271 return String.Empty;
16272 }
16273
16274 public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers)
16275 {
16276 OSD o = OSDParser.DeserializeJson(json);
16277 OSD specVal = JsonGetSpecific(o, specifiers, 0);
16278
16279 return specVal.AsString();
16280 }
16281
16282 public LSL_List llJson2List(LSL_String json)
16283 {
16284 try
16285 {
16286 OSD o = OSDParser.DeserializeJson(json);
16287 return (LSL_List)ParseJsonNode(o);
16288 }
16289 catch (Exception)
16290 {
16291 return new LSL_List(ScriptBaseClass.JSON_INVALID);
16292 }
16293 }
16294
16295 private object ParseJsonNode(OSD node)
16296 {
16297 if (node.Type == OSDType.Integer)
16298 return new LSL_Integer(node.AsInteger());
16299 if (node.Type == OSDType.Boolean)
16300 return new LSL_Integer(node.AsBoolean() ? 1 : 0);
16301 if (node.Type == OSDType.Real)
16302 return new LSL_Float(node.AsReal());
16303 if (node.Type == OSDType.UUID || node.Type == OSDType.String)
16304 return new LSL_String(node.AsString());
16305 if (node.Type == OSDType.Array)
16306 {
16307 LSL_List resp = new LSL_List();
16308 OSDArray ar = node as OSDArray;
16309 foreach (OSD o in ar)
16310 resp.Add(ParseJsonNode(o));
16311 return resp;
16312 }
16313 if (node.Type == OSDType.Map)
16314 {
16315 LSL_List resp = new LSL_List();
16316 OSDMap ar = node as OSDMap;
16317 foreach (KeyValuePair<string, OSD> o in ar)
16318 {
16319 resp.Add(new LSL_String(o.Key));
16320 resp.Add(ParseJsonNode(o.Value));
16321 }
16322 return resp;
16323 }
16324 throw new Exception(ScriptBaseClass.JSON_INVALID);
16325 }
16326
16327 public LSL_String llList2Json(LSL_String type, LSL_List values)
16328 {
16329 try
16330 {
16331 if (type == ScriptBaseClass.JSON_ARRAY)
16332 {
16333 OSDArray array = new OSDArray();
16334 foreach (object o in values.Data)
16335 {
16336 array.Add(ListToJson(o));
16337 }
16338 return OSDParser.SerializeJsonString(array);
16339 }
16340 else if (type == ScriptBaseClass.JSON_OBJECT)
16341 {
16342 OSDMap map = new OSDMap();
16343 for (int i = 0; i < values.Data.Length; i += 2)
16344 {
16345 if (!(values.Data[i] is LSL_String))
16346 return ScriptBaseClass.JSON_INVALID;
16347 map.Add(((LSL_String)values.Data[i]).m_string, ListToJson(values.Data[i + 1]));
16348 }
16349 return OSDParser.SerializeJsonString(map);
16350 }
16351 return ScriptBaseClass.JSON_INVALID;
16352 }
16353 catch (Exception ex)
16354 {
16355 return ex.Message;
16356 }
16357 }
16358
16359 private OSD ListToJson(object o)
16360 {
16361 if (o is LSL_Float)
16362 return OSD.FromReal(((LSL_Float)o).value);
16363 if (o is LSL_Integer)
16364 {
16365 int i = ((LSL_Integer)o).value;
16366 if (i == 0)
16367 return OSD.FromBoolean(false);
16368 else if (i == 1)
16369 return OSD.FromBoolean(true);
16370 return OSD.FromInteger(i);
16371 }
16372 if (o is LSL_Rotation)
16373 return OSD.FromString(((LSL_Rotation)o).ToString());
16374 if (o is LSL_Vector)
16375 return OSD.FromString(((LSL_Vector)o).ToString());
16376 if (o is LSL_String)
16377 {
16378 string str = ((LSL_String)o).m_string;
16379 if (str == ScriptBaseClass.JSON_NULL)
16380 return new OSD();
16381 return OSD.FromString(str);
16382 }
16383 throw new Exception(ScriptBaseClass.JSON_INVALID);
16384 }
16385
16386 private OSD JsonGetSpecific(OSD o, LSL_List specifiers, int i)
16387 {
16388 object spec = specifiers.Data[i];
16389 OSD nextVal = null;
16390 if (o is OSDArray)
16391 {
16392 if (spec is LSL_Integer)
16393 nextVal = ((OSDArray)o)[((LSL_Integer)spec).value];
16394 }
16395 if (o is OSDMap)
16396 {
16397 if (spec is LSL_String)
16398 nextVal = ((OSDMap)o)[((LSL_String)spec).m_string];
16399 }
16400 if (nextVal != null)
16401 {
16402 if (specifiers.Data.Length - 1 > i)
16403 return JsonGetSpecific(nextVal, specifiers, i + 1);
16404 }
16405 return nextVal;
16406 }
16407
16408 public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value)
16409 {
16410 try
16411 {
16412 OSD o = OSDParser.DeserializeJson(json);
16413 JsonSetSpecific(o, specifiers, 0, value);
16414 return OSDParser.SerializeJsonString(o);
16415 }
16416 catch (Exception)
16417 {
16418 }
16419 return ScriptBaseClass.JSON_INVALID;
16420 }
16421
16422 private void JsonSetSpecific(OSD o, LSL_List specifiers, int i, LSL_String val)
16423 {
16424 object spec = specifiers.Data[i];
16425 // 20131224 not used object specNext = i+1 == specifiers.Data.Length ? null : specifiers.Data[i+1];
16426 OSD nextVal = null;
16427 if (o is OSDArray)
16428 {
16429 OSDArray array = ((OSDArray)o);
16430 if (spec is LSL_Integer)
16431 {
16432 int v = ((LSL_Integer)spec).value;
16433 if (v >= array.Count)
16434 array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
16435 else
16436 nextVal = ((OSDArray)o)[v];
16437 }
16438 else if (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND)
16439 array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
16440 }
16441 if (o is OSDMap)
16442 {
16443 if (spec is LSL_String)
16444 {
16445 OSDMap map = ((OSDMap)o);
16446 if (map.ContainsKey(((LSL_String)spec).m_string))
16447 nextVal = map[((LSL_String)spec).m_string];
16448 else
16449 map.Add(((LSL_String)spec).m_string, JsonBuildRestOfSpec(specifiers, i + 1, val));
16450 }
16451 }
16452 if (nextVal != null)
16453 {
16454 if (specifiers.Data.Length - 1 > i)
16455 {
16456 JsonSetSpecific(nextVal, specifiers, i + 1, val);
16457 return;
16458 }
16459 }
16460 }
16461
16462 private OSD JsonBuildRestOfSpec(LSL_List specifiers, int i, LSL_String val)
16463 {
16464 object spec = i >= specifiers.Data.Length ? null : specifiers.Data[i];
16465 // 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1];
16466
16467 if (spec == null)
16468 return OSD.FromString(val);
16469
16470 if (spec is LSL_Integer ||
16471 (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND))
16472 {
16473 OSDArray array = new OSDArray();
16474 array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val));
16475 return array;
16476 }
16477 else if (spec is LSL_String)
16478 {
16479 OSDMap map = new OSDMap();
16480 map.Add((LSL_String)spec, JsonBuildRestOfSpec(specifiers, i + 1, val));
16481 return map;
16482 }
16483 return new OSD();
16484 }
16485
16486 public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers)
16487 {
16488 OSD o = OSDParser.DeserializeJson(json);
16489 OSD specVal = JsonGetSpecific(o, specifiers, 0);
16490 if (specVal == null)
16491 return ScriptBaseClass.JSON_INVALID;
16492 switch (specVal.Type)
16493 {
16494 case OSDType.Array:
16495 return ScriptBaseClass.JSON_ARRAY;
16496 case OSDType.Boolean:
16497 return specVal.AsBoolean() ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE;
16498 case OSDType.Integer:
16499 case OSDType.Real:
16500 return ScriptBaseClass.JSON_NUMBER;
16501 case OSDType.Map:
16502 return ScriptBaseClass.JSON_OBJECT;
16503 case OSDType.String:
16504 case OSDType.UUID:
16505 return ScriptBaseClass.JSON_STRING;
16506 case OSDType.Unknown:
16507 return ScriptBaseClass.JSON_NULL;
16508 }
16509 return ScriptBaseClass.JSON_INVALID;
16510 }
15135 } 16511 }
15136 16512
15137 public class NotecardCache 16513 public class NotecardCache
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 1458c95..7bd4fa7 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -136,7 +136,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
136// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType); 136// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
137 137
138 Type returntype = m_comms.LookupReturnType(fname); 138 Type returntype = m_comms.LookupReturnType(fname);
139 if (returntype != typeof(string)) 139 if (returntype != typeof(void))
140 MODError(String.Format("return type mismatch for {0}",fname)); 140 MODError(String.Format("return type mismatch for {0}",fname));
141 141
142 modInvoke(fname,parms); 142 modInvoke(fname,parms);
@@ -329,6 +329,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
329 if (result != null) 329 if (result != null)
330 return result; 330 return result;
331 331
332 Type returntype = m_comms.LookupReturnType(fname);
333 if (returntype == typeof(void))
334 return null;
335
332 MODError(String.Format("Invocation of {0} failed; null return value",fname)); 336 MODError(String.Format("Invocation of {0} failed; null return value",fname));
333 } 337 }
334 catch (Exception e) 338 catch (Exception e)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index e799714..29f5a83 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -140,8 +140,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
140 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; 140 internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow;
141 internal float m_ScriptDelayFactor = 1.0f; 141 internal float m_ScriptDelayFactor = 1.0f;
142 internal float m_ScriptDistanceFactor = 1.0f; 142 internal float m_ScriptDistanceFactor = 1.0f;
143 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 143 internal bool m_debuggerSafe = false;
144 144 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
145 protected IUrlModule m_UrlModule = null; 145 protected IUrlModule m_UrlModule = null;
146 146
147 public void Initialize( 147 public void Initialize(
@@ -150,6 +150,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
150 m_ScriptEngine = scriptEngine; 150 m_ScriptEngine = scriptEngine;
151 m_host = host; 151 m_host = host;
152 m_item = item; 152 m_item = item;
153 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
153 154
154 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 155 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
155 156
@@ -194,7 +195,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
194 default: 195 default:
195 break; 196 break;
196 } 197 }
197 } 198 }
198 199
199 public override Object InitializeLifetimeService() 200 public override Object InitializeLifetimeService()
200 { 201 {
@@ -216,7 +217,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
216 217
217 internal void OSSLError(string msg) 218 internal void OSSLError(string msg)
218 { 219 {
219 throw new ScriptException("OSSL Runtime Error: " + msg); 220 if (m_debuggerSafe)
221 {
222 OSSLShoutError(msg);
223 }
224 else
225 {
226 throw new ScriptException("OSSL Runtime Error: " + msg);
227 }
220 } 228 }
221 229
222 /// <summary> 230 /// <summary>
@@ -820,7 +828,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
820 private void TeleportAgent(string agent, int regionX, int regionY, 828 private void TeleportAgent(string agent, int regionX, int regionY,
821 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) 829 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
822 { 830 {
823 // ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize));
824 ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY); 831 ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY);
825 832
826 m_host.AddScriptLPS(1); 833 m_host.AddScriptLPS(1);
@@ -993,18 +1000,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
993 if (target != null) 1000 if (target != null)
994 { 1001 {
995 UUID animID=UUID.Zero; 1002 UUID animID=UUID.Zero;
996 lock (m_host.TaskInventory) 1003 m_host.TaskInventory.LockItemsForRead(true);
1004 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
997 { 1005 {
998 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 1006 if (inv.Value.Name == animation)
999 { 1007 {
1000 if (inv.Value.Name == animation) 1008 if (inv.Value.Type == (int)AssetType.Animation)
1001 { 1009 animID = inv.Value.AssetID;
1002 if (inv.Value.Type == (int)AssetType.Animation) 1010 continue;
1003 animID = inv.Value.AssetID;
1004 continue;
1005 }
1006 } 1011 }
1007 } 1012 }
1013 m_host.TaskInventory.LockItemsForRead(false);
1008 if (animID == UUID.Zero) 1014 if (animID == UUID.Zero)
1009 target.Animator.AddAnimation(animation, m_host.UUID); 1015 target.Animator.AddAnimation(animation, m_host.UUID);
1010 else 1016 else
@@ -1046,6 +1052,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1046 animID = UUID.Zero; 1052 animID = UUID.Zero;
1047 } 1053 }
1048 1054
1055
1049 if (animID == UUID.Zero) 1056 if (animID == UUID.Zero)
1050 target.Animator.RemoveAnimation(animation); 1057 target.Animator.RemoveAnimation(animation);
1051 else 1058 else
@@ -1487,7 +1494,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1487 return; 1494 return;
1488 } 1495 }
1489 1496
1490 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, startLandObject, GroupPowers.LandOptions)) 1497 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, startLandObject, GroupPowers.LandOptions, false))
1491 { 1498 {
1492 OSSLShoutError("You do not have permission to modify the parcel"); 1499 OSSLShoutError("You do not have permission to modify the parcel");
1493 return; 1500 return;
@@ -1934,15 +1941,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1934 { 1941 {
1935 UUID assetID = UUID.Zero; 1942 UUID assetID = UUID.Zero;
1936 1943
1937 if (!UUID.TryParse(notecardNameOrUuid, out assetID)) 1944 bool notecardNameIsUUID = UUID.TryParse(notecardNameOrUuid, out assetID);
1945
1946 if (!notecardNameIsUUID)
1938 { 1947 {
1939 foreach (TaskInventoryItem item in m_host.TaskInventory.Values) 1948 assetID = SearchTaskInventoryForAssetId(notecardNameOrUuid);
1940 {
1941 if (item.Type == 7 && item.Name == notecardNameOrUuid)
1942 {
1943 assetID = item.AssetID;
1944 }
1945 }
1946 } 1949 }
1947 1950
1948 if (assetID == UUID.Zero) 1951 if (assetID == UUID.Zero)
@@ -1953,13 +1956,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1953 AssetBase a = World.AssetService.Get(assetID.ToString()); 1956 AssetBase a = World.AssetService.Get(assetID.ToString());
1954 1957
1955 if (a == null) 1958 if (a == null)
1956 return UUID.Zero; 1959 {
1960 // Whoops, it's still possible here that the notecard name was properly
1961 // formatted like a UUID but isn't an asset UUID so lets look it up by name after all
1962 assetID = SearchTaskInventoryForAssetId(notecardNameOrUuid);
1963 if (assetID == UUID.Zero)
1964 return UUID.Zero;
1965
1966 if (!NotecardCache.IsCached(assetID))
1967 {
1968 a = World.AssetService.Get(assetID.ToString());
1969
1970 if (a == null)
1971 {
1972 return UUID.Zero;
1973 }
1974 }
1975 }
1957 1976
1958 NotecardCache.Cache(assetID, a.Data); 1977 NotecardCache.Cache(assetID, a.Data);
1959 }; 1978 };
1960 1979
1961 return assetID; 1980 return assetID;
1962 } 1981 }
1982 protected UUID SearchTaskInventoryForAssetId(string name)
1983 {
1984 UUID assetId = UUID.Zero;
1985 m_host.TaskInventory.LockItemsForRead(true);
1986 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
1987 {
1988 if (item.Type == 7 && item.Name == name)
1989 {
1990 assetId = item.AssetID;
1991 }
1992 }
1993 m_host.TaskInventory.LockItemsForRead(false);
1994 return assetId;
1995 }
1963 1996
1964 /// <summary> 1997 /// <summary>
1965 /// Directly get an entire notecard at once. 1998 /// Directly get an entire notecard at once.
@@ -2543,8 +2576,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2543 { 2576 {
2544 CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); 2577 CheckThreatLevel(ThreatLevel.High, "osNpcCreate");
2545 m_host.AddScriptLPS(1); 2578 m_host.AddScriptLPS(1);
2579
2580 // have to get the npc module also here to set the default Not Owned
2581 INPCModule module = World.RequestModuleInterface<INPCModule>();
2582 if(module == null)
2583 return new LSL_Key(UUID.Zero.ToString());
2584
2585 bool owned = (module.NPCOptionFlags & NPCOptionsFlags.AllowNotOwned) == 0;
2546 2586
2547 return NpcCreate(firstname, lastname, position, notecard, false, false); 2587 return NpcCreate(firstname, lastname, position, notecard, owned, false);
2548 } 2588 }
2549 2589
2550 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) 2590 public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options)
@@ -2561,17 +2601,49 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2561 private LSL_Key NpcCreate( 2601 private LSL_Key NpcCreate(
2562 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) 2602 string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent)
2563 { 2603 {
2604
2605 if (!World.Permissions.CanRezObject(1, m_host.OwnerID, new Vector3((float)position.x, (float)position.y, (float)position.z)))
2606 return new LSL_Key(UUID.Zero.ToString());
2607
2564 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2608 INPCModule module = World.RequestModuleInterface<INPCModule>();
2565 if (module != null) 2609 if (module != null)
2566 { 2610 {
2611 string groupTitle = String.Empty;
2567 AvatarAppearance appearance = null; 2612 AvatarAppearance appearance = null;
2568 2613
2569 UUID id; 2614 // check creation options
2570 if (UUID.TryParse(notecard, out id)) 2615 NPCOptionsFlags createFlags = module.NPCOptionFlags;
2616
2617 if((createFlags & NPCOptionsFlags.AllowNotOwned) == 0 && !owned)
2618 {
2619 OSSLError("Not owned NPCs disabled");
2620 owned = true; // we should get here...
2621 }
2622
2623 if((createFlags & NPCOptionsFlags.AllowSenseAsAvatar) == 0 && senseAsAgent)
2624 {
2625 OSSLError("NPC allow sense as Avatar disabled");
2626 senseAsAgent = false;
2627 }
2628
2629 if((createFlags & NPCOptionsFlags.NoNPCGroup) == 0)
2630 {
2631 if (firstname != String.Empty || lastname != String.Empty)
2632 {
2633 if (firstname != "Shown outfit:")
2634 groupTitle = "- NPC -";
2635 }
2636 }
2637
2638 if((createFlags & NPCOptionsFlags.AllowCloneOtherAvatars) != 0)
2571 { 2639 {
2572 ScenePresence clonePresence = World.GetScenePresence(id); 2640 UUID id;
2573 if (clonePresence != null) 2641 if (UUID.TryParse(notecard, out id))
2574 appearance = clonePresence.Appearance; 2642 {
2643 ScenePresence clonePresence = World.GetScenePresence(id);
2644 if (clonePresence != null)
2645 appearance = clonePresence.Appearance;
2646 }
2575 } 2647 }
2576 2648
2577 if (appearance == null) 2649 if (appearance == null)
@@ -2580,9 +2652,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2580 2652
2581 if (appearanceSerialized != null) 2653 if (appearanceSerialized != null)
2582 { 2654 {
2583 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); 2655 try
2584 appearance = new AvatarAppearance(); 2656 {
2585 appearance.Unpack(appearanceOsd); 2657 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized);
2658 appearance = new AvatarAppearance();
2659 appearance.Unpack(appearanceOsd);
2660 }
2661 catch
2662 {
2663 return UUID.Zero.ToString();
2664 }
2586 } 2665 }
2587 else 2666 else
2588 { 2667 {
@@ -2601,6 +2680,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2601 World, 2680 World,
2602 appearance); 2681 appearance);
2603 2682
2683 ScenePresence sp;
2684 if (World.TryGetScenePresence(x, out sp))
2685 {
2686 sp.Grouptitle = groupTitle;
2687 sp.SendAvatarDataToAllAgents();
2688 }
2604 return new LSL_Key(x.ToString()); 2689 return new LSL_Key(x.ToString());
2605 } 2690 }
2606 2691
@@ -2898,16 +2983,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2898 CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); 2983 CheckThreatLevel(ThreatLevel.High, "osNpcRemove");
2899 m_host.AddScriptLPS(1); 2984 m_host.AddScriptLPS(1);
2900 2985
2901 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2986 try
2902 if (module != null)
2903 { 2987 {
2904 UUID npcId = new UUID(npc.m_string); 2988 INPCModule module = World.RequestModuleInterface<INPCModule>();
2989 if (module != null)
2990 {
2991 UUID npcId = new UUID(npc.m_string);
2905 2992
2906 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2993 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2907 return; 2994 return;
2908 2995
2909 module.DeleteNPC(npcId, World); 2996 module.DeleteNPC(npcId, World);
2997 }
2910 } 2998 }
2999 catch { }
2911 } 3000 }
2912 3001
2913 public void osNpcPlayAnimation(LSL_Key npc, string animation) 3002 public void osNpcPlayAnimation(LSL_Key npc, string animation)
@@ -3025,7 +3114,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3025 if (appearanceModule != null) 3114 if (appearanceModule != null)
3026 { 3115 {
3027 appearanceModule.SaveBakedTextures(sp.UUID); 3116 appearanceModule.SaveBakedTextures(sp.UUID);
3028 OSDMap appearancePacked = sp.Appearance.Pack(); 3117 EntityTransferContext ctx = new EntityTransferContext();
3118 OSDMap appearancePacked = sp.Appearance.Pack(ctx);
3029 3119
3030 TaskInventoryItem item 3120 TaskInventoryItem item
3031 = SaveNotecard(notecard, "Avatar Appearance", Util.GetFormattedXml(appearancePacked as OSD), true); 3121 = SaveNotecard(notecard, "Avatar Appearance", Util.GetFormattedXml(appearancePacked as OSD), true);
@@ -3185,7 +3275,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3185 { 3275 {
3186 Scene scene = m_ScriptEngine.World; 3276 Scene scene = m_ScriptEngine.World;
3187 GridRegion region = scene.GridService.GetRegionByUUID(UUID.Zero, World.RegionInfo.RegionID); 3277 GridRegion region = scene.GridService.GetRegionByUUID(UUID.Zero, World.RegionInfo.RegionID);
3188 return new LSL_Vector((float)region.RegionSizeX, (float)region.RegionSizeX, Constants.RegionHeight); 3278 return new LSL_Vector((float)region.RegionSizeX, (float)region.RegionSizeY, (float)Constants.RegionHeight);
3189 } 3279 }
3190 } 3280 }
3191 3281
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 64dc2e2..7bfe27b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -93,7 +93,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
93 private const int AGENT = 1; 93 private const int AGENT = 1;
94 private const int AGENT_BY_USERNAME = 0x10; 94 private const int AGENT_BY_USERNAME = 0x10;
95 private const int NPC = 0x20; 95 private const int NPC = 0x20;
96 private const int OS_NPC = 0x01000000;
97 private const int ACTIVE = 2; 96 private const int ACTIVE = 2;
98 private const int PASSIVE = 4; 97 private const int PASSIVE = 4;
99 private const int SCRIPTED = 8; 98 private const int SCRIPTED = 8;
@@ -240,7 +239,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
240 List<SensedEntity> sensedEntities = new List<SensedEntity>(); 239 List<SensedEntity> sensedEntities = new List<SensedEntity>();
241 240
242 // Is the sensor type is AGENT and not SCRIPTED then include agents 241 // Is the sensor type is AGENT and not SCRIPTED then include agents
243 if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC | OS_NPC)) != 0 && (ts.type & SCRIPTED) == 0) 242 if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0)
244 { 243 {
245 sensedEntities.AddRange(doAgentSensor(ts)); 244 sensedEntities.AddRange(doAgentSensor(ts));
246 } 245 }
@@ -339,7 +338,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
339 float dy; 338 float dy;
340 float dz; 339 float dz;
341 340
342 Quaternion q = SensePoint.GetWorldRotation(); 341// Quaternion q = SensePoint.RotationOffset;
342 Quaternion q = SensePoint.GetWorldRotation(); // non-attached prim Sensor *always* uses World rotation!
343 if (SensePoint.ParentGroup.IsAttachment) 343 if (SensePoint.ParentGroup.IsAttachment)
344 { 344 {
345 // In attachments, rotate the sensor cone with the 345 // In attachments, rotate the sensor cone with the
@@ -358,7 +358,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
358 if (avatar == null) 358 if (avatar == null)
359 return sensedEntities; 359 return sensedEntities;
360 360
361 q = avatar.GetWorldRotation() * q; 361 fromRegionPos = avatar.AbsolutePosition;
362 q = avatar.Rotation;
362 } 363 }
363 364
364 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); 365 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
@@ -402,7 +403,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
402 objtype = 0; 403 objtype = 0;
403 404
404 part = ((SceneObjectGroup)ent).RootPart; 405 part = ((SceneObjectGroup)ent).RootPart;
405 if (part.ParentGroup.AttachmentPoint != 0) // Attached so ignore 406 if (part.ParentGroup.RootPart.Shape.PCode != (byte)PCode.Tree &&
407 part.ParentGroup.RootPart.Shape.PCode != (byte)PCode.NewTree &&
408 part.ParentGroup.AttachmentPoint != 0) // Attached so ignore
406 continue; 409 continue;
407 410
408 if (part.Inventory.ContainsScripts()) 411 if (part.Inventory.ContainsScripts())
@@ -489,8 +492,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
489 // Don't proceed if the avatar for this attachment has since been removed from the scene. 492 // Don't proceed if the avatar for this attachment has since been removed from the scene.
490 if (avatar == null) 493 if (avatar == null)
491 return sensedEntities; 494 return sensedEntities;
492 495 fromRegionPos = avatar.AbsolutePosition;
493 q = avatar.GetWorldRotation() * q; 496 q = avatar.Rotation;
494 } 497 }
495 498
496 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); 499 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
@@ -506,7 +509,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
506// "[SENSOR REPEAT]: Inspecting scene presence {0}, type {1} on sensor sweep for {2}, type {3}", 509// "[SENSOR REPEAT]: Inspecting scene presence {0}, type {1} on sensor sweep for {2}, type {3}",
507// presence.Name, presence.PresenceType, ts.name, ts.type); 510// presence.Name, presence.PresenceType, ts.name, ts.type);
508 511
509 if ((ts.type & NPC) == 0 && (ts.type & OS_NPC) == 0 && presence.PresenceType == PresenceType.Npc) 512 if ((ts.type & NPC) == 0 && presence.PresenceType == PresenceType.Npc)
510 { 513 {
511 INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene); 514 INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene);
512 if (npcData == null || !npcData.SenseAsAgent) 515 if (npcData == null || !npcData.SenseAsAgent)
@@ -546,7 +549,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
546 return; 549 return;
547 550
548 toRegionPos = presence.AbsolutePosition; 551 toRegionPos = presence.AbsolutePosition;
549 dis = Math.Abs(Util.GetDistanceTo(toRegionPos, fromRegionPos)); 552 dis = Util.GetDistanceTo(toRegionPos, fromRegionPos);
553 if (presence.IsSatOnObject && presence.ParentPart != null &&
554 presence.ParentPart.ParentGroup != null &&
555 presence.ParentPart.ParentGroup.RootPart != null)
556 {
557 Vector3 rpos = presence.ParentPart.ParentGroup.RootPart.AbsolutePosition;
558 double dis2 = Util.GetDistanceTo(rpos, fromRegionPos);
559 if (dis > dis2)
560 dis = dis2;
561 }
550 562
551 // Disabled for now since all osNpc* methods check for appropriate ownership permission. 563 // Disabled for now since all osNpc* methods check for appropriate ownership permission.
552 // Perhaps could be re-enabled as an NPC setting at some point since being able to make NPCs not 564 // Perhaps could be re-enabled as an NPC setting at some point since being able to make NPCs not
@@ -706,4 +718,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
706 return retList; 718 return retList;
707 } 719 }
708 } 720 }
709} \ No newline at end of file 721}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
index 0b14565..5b1fdc0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs
@@ -123,25 +123,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
123 if (Timers.Count == 0) 123 if (Timers.Count == 0)
124 return; 124 return;
125 125
126 Dictionary<string, TimerInfo> tvals;
126 lock (TimerListLock) 127 lock (TimerListLock)
127 { 128 {
128 // Go through all timers 129 // Go through all timers
129 Dictionary<string, TimerInfo>.ValueCollection tvals = Timers.Values; 130 tvals = new Dictionary<string, TimerInfo>(Timers);
130 foreach (TimerInfo ts in tvals) 131 }
132
133 foreach (TimerInfo ts in tvals.Values)
134 {
135 // Time has passed?
136 if (ts.next < DateTime.Now.Ticks)
131 { 137 {
132 // Time has passed? 138 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
133 if (ts.next < DateTime.Now.Ticks) 139 // Add it to queue
134 { 140 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
135 //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); 141 new EventParams("timer", new Object[0],
136 // Add it to queue 142 new DetectParams[0]));
137 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 143 // set next interval
138 new EventParams("timer", new Object[0], 144
139 new DetectParams[0])); 145 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
140 // set next interval 146 ts.next = DateTime.Now.Ticks + ts.interval;
141
142 //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
143 ts.next = DateTime.Now.Ticks + ts.interval;
144 }
145 } 147 }
146 } 148 }
147 } 149 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs
new file mode 100644
index 0000000..ab215f3
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.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.Collections;
29using OpenSim.Region.ScriptEngine.Interfaces;
30
31using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
32using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
33using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
34using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
35using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
36using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
37using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
38
39namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
40{
41 public interface ICM_Api
42 {
43 string cmDetectedCountry(int num);
44 string cmGetAgentCountry(key key);
45 }
46}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 3d58573..8b8638c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -127,6 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
127 LSL_String llGetEnv(LSL_String name); 127 LSL_String llGetEnv(LSL_String name);
128 LSL_Vector llGetForce(); 128 LSL_Vector llGetForce();
129 LSL_Integer llGetFreeMemory(); 129 LSL_Integer llGetFreeMemory();
130 LSL_Integer llGetUsedMemory();
130 LSL_Integer llGetFreeURLs(); 131 LSL_Integer llGetFreeURLs();
131 LSL_Vector llGetGeometricCenter(); 132 LSL_Vector llGetGeometricCenter();
132 LSL_Float llGetGMTclock(); 133 LSL_Float llGetGMTclock();
@@ -204,12 +205,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
204 LSL_String llGetTimestamp(); 205 LSL_String llGetTimestamp();
205 LSL_Vector llGetTorque(); 206 LSL_Vector llGetTorque();
206 LSL_Integer llGetUnixTime(); 207 LSL_Integer llGetUnixTime();
207 LSL_Integer llGetUsedMemory();
208 LSL_Vector llGetVel(); 208 LSL_Vector llGetVel();
209 LSL_Float llGetWallclock(); 209 LSL_Float llGetWallclock();
210 void llGiveInventory(string destination, string inventory); 210 void llGiveInventory(string destination, string inventory);
211 void llGiveInventoryList(string destination, string category, LSL_List inventory); 211 void llGiveInventoryList(string destination, string category, LSL_List inventory);
212 void llGiveMoney(string destination, int amount); 212 LSL_Integer llGiveMoney(string destination, int amount);
213 LSL_String llTransferLindenDollars(string destination, int amount); 213 LSL_String llTransferLindenDollars(string destination, int amount);
214 void llGodLikeRezObject(string inventory, LSL_Vector pos); 214 void llGodLikeRezObject(string inventory, LSL_Vector pos);
215 LSL_Float llGround(LSL_Vector offset); 215 LSL_Float llGround(LSL_Vector offset);
@@ -344,7 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
344 void llSetDamage(double damage); 344 void llSetDamage(double damage);
345 void llSetForce(LSL_Vector force, int local); 345 void llSetForce(LSL_Vector force, int local);
346 void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local); 346 void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local);
347 void llSetVelocity(LSL_Vector velocity, int local); 347 void llSetVelocity(LSL_Vector vel, int local);
348 void llSetAngularVelocity(LSL_Vector angularVelocity, int local); 348 void llSetAngularVelocity(LSL_Vector angularVelocity, int local);
349 void llSetHoverHeight(double height, int water, double tau); 349 void llSetHoverHeight(double height, int water, double tau);
350 void llSetInventoryPermMask(string item, int mask, int value); 350 void llSetInventoryPermMask(string item, int mask, int value);
@@ -362,11 +362,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
362 void llSetParcelMusicURL(string url); 362 void llSetParcelMusicURL(string url);
363 void llSetPayPrice(int price, LSL_List quick_pay_buttons); 363 void llSetPayPrice(int price, LSL_List quick_pay_buttons);
364 void llSetPos(LSL_Vector pos); 364 void llSetPos(LSL_Vector pos);
365 LSL_Integer llSetRegionPos(LSL_Vector pos);
365 LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules); 366 LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules);
366 void llSetPrimitiveParams(LSL_List rules); 367 void llSetPrimitiveParams(LSL_List rules);
367 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); 368 void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules);
368 void llSetPrimURL(string url); 369 void llSetPrimURL(string url);
369 LSL_Integer llSetRegionPos(LSL_Vector pos);
370 void llSetRemoteScriptAccessPin(int pin); 370 void llSetRemoteScriptAccessPin(int pin);
371 void llSetRot(LSL_Rotation rot); 371 void llSetRot(LSL_Rotation rot);
372 void llSetScale(LSL_Vector scale); 372 void llSetScale(LSL_Vector scale);
@@ -429,10 +429,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
429 LSL_Vector llWind(LSL_Vector offset); 429 LSL_Vector llWind(LSL_Vector offset);
430 LSL_String llXorBase64Strings(string str1, string str2); 430 LSL_String llXorBase64Strings(string str1, string str2);
431 LSL_String llXorBase64StringsCorrect(string str1, string str2); 431 LSL_String llXorBase64StringsCorrect(string str1, string str2);
432 void print(string str); 432 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
433 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density);
433 434
434 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc); 435 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc);
435 void llSetKeyframedMotion(LSL_List frames, LSL_List options); 436 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
436 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 437 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
438 LSL_List llGetPhysicsMaterial();
439 void llSetAnimationOverride(LSL_String animState, LSL_String anim);
440 void llResetAnimationOverride(LSL_String anim_state);
441 LSL_String llGetAnimationOverride(LSL_String anim_state);
442 LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers);
443 LSL_List llJson2List(LSL_String json);
444 LSL_String llList2Json(LSL_String type, LSL_List values);
445 LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value);
446 LSL_String llJsonValueType(LSL_String json, LSL_List specifiers);
437 } 447 }
438} 448}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 6259b76..4e567e6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -144,7 +144,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
144 // Avatar Info Commands 144 // Avatar Info Commands
145 string osGetAgentIP(string agent); 145 string osGetAgentIP(string agent);
146 LSL_List osGetAgents(); 146 LSL_List osGetAgents();
147 147
148 // Teleport commands 148 // Teleport commands
149 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 149 void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
150 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); 150 void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs
new file mode 100644
index 0000000..4132dfa
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.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.Runtime.Remoting.Lifetime;
30using System.Threading;
31using System.Reflection;
32using System.Collections;
33using System.Collections.Generic;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
38using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
39using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
40using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
41using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
42using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
43using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
44using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
45using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
46
47namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
48{
49 public partial class ScriptBaseClass : MarshalByRefObject
50 {
51 public ICM_Api m_CM_Functions;
52
53 public void ApiTypeCM(IScriptApi api)
54 {
55 if (!(api is ICM_Api))
56 return;
57
58 m_CM_Functions = (ICM_Api)api;
59 }
60
61 public string cmDetectedCountry(int num)
62 {
63 return m_CM_Functions.cmDetectedCountry(num);
64 }
65
66 public string cmGetAgentCountry(key key)
67 {
68 return m_CM_Functions.cmGetAgentCountry(key);
69 }
70 }
71}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
index ce17ed0..1cc2cfb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics; //for [DebuggerNonUserCode]
30using System.Reflection; 31using System.Reflection;
31using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
32using OpenSim.Region.ScriptEngine.Shared; 33using OpenSim.Region.ScriptEngine.Shared;
@@ -133,6 +134,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
133 return (eventFlags); 134 return (eventFlags);
134 } 135 }
135 136
137 [DebuggerNonUserCode]
136 public void ExecuteEvent(string state, string FunctionName, object[] args) 138 public void ExecuteEvent(string state, string FunctionName, object[] args)
137 { 139 {
138 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. 140 // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 9aecea2..158acc6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -57,7 +57,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
57 public const int ACTIVE = 2; 57 public const int ACTIVE = 2;
58 public const int PASSIVE = 4; 58 public const int PASSIVE = 4;
59 public const int SCRIPTED = 8; 59 public const int SCRIPTED = 8;
60 public const int OS_NPC = 0x01000000;
61 60
62 public const int CONTROL_FWD = 1; 61 public const int CONTROL_FWD = 1;
63 public const int CONTROL_BACK = 2; 62 public const int CONTROL_BACK = 2;
@@ -82,6 +81,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
82 public const int PERMISSION_CHANGE_PERMISSIONS = 512; 81 public const int PERMISSION_CHANGE_PERMISSIONS = 512;
83 public const int PERMISSION_TRACK_CAMERA = 1024; 82 public const int PERMISSION_TRACK_CAMERA = 1024;
84 public const int PERMISSION_CONTROL_CAMERA = 2048; 83 public const int PERMISSION_CONTROL_CAMERA = 2048;
84 public const int PERMISSION_TELEPORT = 4096;
85 public const int PERMISSION_OVERRIDE_ANIMATIONS = 0x8000;
85 86
86 public const int AGENT_FLYING = 1; 87 public const int AGENT_FLYING = 1;
87 public const int AGENT_ATTACHMENTS = 2; 88 public const int AGENT_ATTACHMENTS = 2;
@@ -96,6 +97,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
96 public const int AGENT_CROUCHING = 1024; 97 public const int AGENT_CROUCHING = 1024;
97 public const int AGENT_BUSY = 2048; 98 public const int AGENT_BUSY = 2048;
98 public const int AGENT_ALWAYS_RUN = 4096; 99 public const int AGENT_ALWAYS_RUN = 4096;
100 public const int AGENT_MALE = 8192;
99 101
100 //Particle Systems 102 //Particle Systems
101 public const int PSYS_PART_INTERP_COLOR_MASK = 1; 103 public const int PSYS_PART_INTERP_COLOR_MASK = 1;
@@ -353,6 +355,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
353 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART 355 public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART
354 public const int CHANGED_MEDIA = 2048; 356 public const int CHANGED_MEDIA = 2048;
355 public const int CHANGED_ANIMATION = 16384; 357 public const int CHANGED_ANIMATION = 16384;
358 public const int CHANGED_POSITION = 32768;
356 public const int TYPE_INVALID = 0; 359 public const int TYPE_INVALID = 0;
357 public const int TYPE_INTEGER = 1; 360 public const int TYPE_INTEGER = 1;
358 public const int TYPE_FLOAT = 2; 361 public const int TYPE_FLOAT = 2;
@@ -708,7 +711,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
708 public const int FRICTION = 2; 711 public const int FRICTION = 2;
709 public const int RESTITUTION = 4; 712 public const int RESTITUTION = 4;
710 public const int GRAVITY_MULTIPLIER = 8; 713 public const int GRAVITY_MULTIPLIER = 8;
711 714
712 // extra constants for llSetPrimMediaParams 715 // extra constants for llSetPrimMediaParams
713 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0); 716 public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0);
714 public static readonly LSLInteger LSL_STATUS_MALFORMED_PARAMS = new LSLInteger(1000); 717 public static readonly LSLInteger LSL_STATUS_MALFORMED_PARAMS = new LSLInteger(1000);
@@ -795,6 +798,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
795 public const int KFM_CMD_STOP = 1; 798 public const int KFM_CMD_STOP = 1;
796 public const int KFM_CMD_PAUSE = 2; 799 public const int KFM_CMD_PAUSE = 2;
797 800
801 public const string JSON_ARRAY = "JSON_ARRAY";
802 public const string JSON_OBJECT = "JSON_OBJECT";
803 public const string JSON_INVALID = "JSON_INVALID";
804 public const string JSON_NUMBER = "JSON_NUMBER";
805 public const string JSON_STRING = "JSON_STRING";
806 public const string JSON_TRUE = "JSON_TRUE";
807 public const string JSON_FALSE = "JSON_FALSE";
808 public const string JSON_NULL = "JSON_NULL";
809 public const string JSON_APPEND = "JSON_APPEND";
810
798 /// <summary> 811 /// <summary>
799 /// process name parameter as regex 812 /// process name parameter as regex
800 /// </summary> 813 /// </summary>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 35aaf01..cea66d2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Diagnostics; //for [DebuggerNonUserCode]
29using System.Runtime.Remoting.Lifetime; 30using System.Runtime.Remoting.Lifetime;
30using System.Threading; 31using System.Threading;
31using System.Reflection; 32using System.Reflection;
@@ -314,6 +315,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
314 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); 315 m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel);
315 } 316 }
316 317
318 [DebuggerNonUserCode]
317 public void llDie() 319 public void llDie()
318 { 320 {
319 m_LSL_Functions.llDie(); 321 m_LSL_Functions.llDie();
@@ -479,6 +481,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
479 return m_LSL_Functions.llGetFreeMemory(); 481 return m_LSL_Functions.llGetFreeMemory();
480 } 482 }
481 483
484 public LSL_Integer llGetUsedMemory()
485 {
486 return m_LSL_Functions.llGetUsedMemory();
487 }
488
482 public LSL_Integer llGetFreeURLs() 489 public LSL_Integer llGetFreeURLs()
483 { 490 {
484 return m_LSL_Functions.llGetFreeURLs(); 491 return m_LSL_Functions.llGetFreeURLs();
@@ -559,11 +566,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
559 return m_LSL_Functions.llGetLinkNumberOfSides(link); 566 return m_LSL_Functions.llGetLinkNumberOfSides(link);
560 } 567 }
561 568
562 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
563 {
564 m_LSL_Functions.llSetKeyframedMotion(frames, options);
565 }
566
567 public LSL_Integer llGetListEntryType(LSL_List src, int index) 569 public LSL_Integer llGetListEntryType(LSL_List src, int index)
568 { 570 {
569 return m_LSL_Functions.llGetListEntryType(src, index); 571 return m_LSL_Functions.llGetListEntryType(src, index);
@@ -859,11 +861,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
859 return m_LSL_Functions.llGetUnixTime(); 861 return m_LSL_Functions.llGetUnixTime();
860 } 862 }
861 863
862 public LSL_Integer llGetUsedMemory()
863 {
864 return m_LSL_Functions.llGetUsedMemory();
865 }
866
867 public LSL_Vector llGetVel() 864 public LSL_Vector llGetVel()
868 { 865 {
869 return m_LSL_Functions.llGetVel(); 866 return m_LSL_Functions.llGetVel();
@@ -884,9 +881,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
884 m_LSL_Functions.llGiveInventoryList(destination, category, inventory); 881 m_LSL_Functions.llGiveInventoryList(destination, category, inventory);
885 } 882 }
886 883
887 public void llGiveMoney(string destination, int amount) 884 public LSL_Integer llGiveMoney(string destination, int amount)
888 { 885 {
889 m_LSL_Functions.llGiveMoney(destination, amount); 886 return m_LSL_Functions.llGiveMoney(destination, amount);
890 } 887 }
891 888
892 public LSL_String llTransferLindenDollars(string destination, int amount) 889 public LSL_String llTransferLindenDollars(string destination, int amount)
@@ -1563,6 +1560,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1563 m_LSL_Functions.llSetVelocity(force, local); 1560 m_LSL_Functions.llSetVelocity(force, local);
1564 } 1561 }
1565 1562
1563
1566 public void llSetAngularVelocity(LSL_Vector force, int local) 1564 public void llSetAngularVelocity(LSL_Vector force, int local)
1567 { 1565 {
1568 m_LSL_Functions.llSetAngularVelocity(force, local); 1566 m_LSL_Functions.llSetAngularVelocity(force, local);
@@ -1643,6 +1641,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1643 m_LSL_Functions.llSetPos(pos); 1641 m_LSL_Functions.llSetPos(pos);
1644 } 1642 }
1645 1643
1644 public LSL_Integer llSetRegionPos(LSL_Vector pos)
1645 {
1646 return m_LSL_Functions.llSetRegionPos(pos);
1647 }
1648
1646 public void llSetPrimitiveParams(LSL_List rules) 1649 public void llSetPrimitiveParams(LSL_List rules)
1647 { 1650 {
1648 m_LSL_Functions.llSetPrimitiveParams(rules); 1651 m_LSL_Functions.llSetPrimitiveParams(rules);
@@ -1658,11 +1661,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1658 m_LSL_Functions.llSetPrimURL(url); 1661 m_LSL_Functions.llSetPrimURL(url);
1659 } 1662 }
1660 1663
1661 public LSL_Integer llSetRegionPos(LSL_Vector pos)
1662 {
1663 return m_LSL_Functions.llSetRegionPos(pos);
1664 }
1665
1666 public void llSetRemoteScriptAccessPin(int pin) 1664 public void llSetRemoteScriptAccessPin(int pin)
1667 { 1665 {
1668 m_LSL_Functions.llSetRemoteScriptAccessPin(pin); 1666 m_LSL_Functions.llSetRemoteScriptAccessPin(pin);
@@ -2008,9 +2006,64 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
2008 return m_LSL_Functions.llClearLinkMedia(link, face); 2006 return m_LSL_Functions.llClearLinkMedia(link, face);
2009 } 2007 }
2010 2008
2011 public void print(string str) 2009 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
2010 {
2011 return m_LSL_Functions.llGetLinkNumberOfSides(link);
2012 }
2013
2014 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
2015 {
2016 m_LSL_Functions.llSetKeyframedMotion(frames, options);
2017 }
2018
2019 public void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density)
2020 {
2021 m_LSL_Functions.llSetPhysicsMaterial(material_bits, material_gravity_modifier, material_restitution, material_friction, material_density);
2022 }
2023
2024 public LSL_List llGetPhysicsMaterial()
2025 {
2026 return m_LSL_Functions.llGetPhysicsMaterial();
2027 }
2028
2029 public void llSetAnimationOverride(LSL_String animState, LSL_String anim)
2030 {
2031 m_LSL_Functions.llSetAnimationOverride(animState, anim);
2032 }
2033
2034 public void llResetAnimationOverride(LSL_String anim_state)
2035 {
2036 m_LSL_Functions.llResetAnimationOverride(anim_state);
2037 }
2038
2039 public LSL_String llGetAnimationOverride(LSL_String anim_state)
2040 {
2041 return m_LSL_Functions.llGetAnimationOverride(anim_state);
2042 }
2043
2044 public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers)
2045 {
2046 return m_LSL_Functions.llJsonGetValue(json, specifiers);
2047 }
2048
2049 public LSL_List llJson2List(LSL_String json)
2050 {
2051 return m_LSL_Functions.llJson2List(json);
2052 }
2053
2054 public LSL_String llList2Json(LSL_String type, LSL_List values)
2055 {
2056 return m_LSL_Functions.llList2Json(type, values);
2057 }
2058
2059 public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value)
2060 {
2061 return m_LSL_Functions.llJsonSetValue(json, specifiers, value);
2062 }
2063
2064 public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers)
2012 { 2065 {
2013 m_LSL_Functions.print(str); 2066 return m_LSL_Functions.llJsonValueType(json, specifiers);
2014 } 2067 }
2015 } 2068 }
2016} 2069}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
index 143b497..2e27f16 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs
@@ -72,9 +72,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
72 { 72 {
73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); 73 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
74 } 74 }
75
75 public void lsClearWindlightScene() 76 public void lsClearWindlightScene()
76 { 77 {
77 m_LS_Functions.lsClearWindlightScene(); 78 m_LS_Functions.lsClearWindlightScene();
78 } 79 }
80
81 public LSL_List cmGetWindlightScene(LSL_List rules)
82 {
83 return m_LS_Functions.lsGetWindlightScene(rules);
84 }
85
86 public int cmSetWindlightScene(LSL_List rules)
87 {
88 return m_LS_Functions.lsSetWindlightScene(rules);
89 }
90
91 public int cmSetWindlightSceneTargeted(LSL_List rules, key target)
92 {
93 return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target);
94 }
95
96 public void cmClearWindlightScene()
97 {
98 m_LS_Functions.lsClearWindlightScene();
99 }
79 } 100 }
80} 101}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index a60f381..31393bb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -439,7 +439,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
439 { 439 {
440 return m_OSSL_Functions.osParseJSON(JSON); 440 return m_OSSL_Functions.osParseJSON(JSON);
441 } 441 }
442 442
443 public Object osParseJSONNew(string JSON) 443 public Object osParseJSONNew(string JSON)
444 { 444 {
445 return m_OSSL_Functions.osParseJSONNew(JSON); 445 return m_OSSL_Functions.osParseJSONNew(JSON);
@@ -744,14 +744,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
744 if (Position.y > ((int)Constants.RegionSize - 1)) 744 if (Position.y > ((int)Constants.RegionSize - 1))
745 Position.y = ((int)Constants.RegionSize - 1); 745 Position.y = ((int)Constants.RegionSize - 1);
746 */ 746 */
747 if (Position.z > Constants.RegionHeight)
748 Position.z = Constants.RegionHeight;
749 if (Position.x < 0) 747 if (Position.x < 0)
750 Position.x = 0; 748 Position.x = 0;
751 if (Position.y < 0) 749 if (Position.y < 0)
752 Position.y = 0; 750 Position.y = 0;
753 if (Position.z < 0) 751 if (Position.z < 0)
754 Position.z = 0; 752 Position.z = 0;
753 if (Position.z > Constants.RegionHeight)
754 Position.z = Constants.RegionHeight;
755 prim.OSSL.llSetPos(Position); 755 prim.OSSL.llSetPos(Position);
756 } 756 }
757 757
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp
deleted file mode 100644
index f02d2d9..0000000
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp
+++ /dev/null
@@ -1,48 +0,0 @@
1<Project name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime" description="" standardNamespace="OpenSim.Region.ScriptEngine.Shared.Api.Runtime" newfilesearch="None" enableviewstate="True" fileversion="2.0" language="C#" clr-version="Net_2_0" ctype="DotNetProject">
2 <Configurations active="Debug">
3 <Configuration name="Debug" ctype="DotNetProjectConfiguration">
4 <Output directory="./../../../../../../bin/" assembly="OpenSim.Region.ScriptEngine.Shared.Api.Runtime" executeScript="" executeBeforeBuild="" executeAfterBuild="" executeBeforeBuildArguments="" executeAfterBuildArguments="" />
5 <Build debugmode="True" target="Library" />
6 <Execution runwithwarnings="True" consolepause="True" runtime="MsNet" clr-version="Net_2_0" />
7 <CodeGeneration compiler="Csc" warninglevel="4" nowarn="" includedebuginformation="True" optimize="False" unsafecodeallowed="False" generateoverflowchecks="False" mainclass="" target="Library" definesymbols="TRACE;DEBUG" generatexmldocumentation="False" win32Icon="" ctype="CSharpCompilerParameters" />
8 </Configuration>
9 <Configuration name="Release" ctype="DotNetProjectConfiguration">
10 <Output directory="./../../../../../../bin/" assembly="OpenSim.Region.ScriptEngine.Shared.Api.Runtime" executeScript="" executeBeforeBuild="" executeAfterBuild="" executeBeforeBuildArguments="" executeAfterBuildArguments="" />
11 <Build debugmode="True" target="Library" />
12 <Execution runwithwarnings="True" consolepause="True" runtime="MsNet" clr-version="Net_2_0" />
13 <CodeGeneration compiler="Csc" warninglevel="4" nowarn="" includedebuginformation="False" optimize="True" unsafecodeallowed="False" generateoverflowchecks="False" mainclass="" target="Library" definesymbols="TRACE" generatexmldocumentation="False" win32Icon="" ctype="CSharpCompilerParameters" />
14 </Configuration>
15 </Configurations>
16 <DeploymentInformation target="" script="" strategy="File">
17 <excludeFiles />
18 </DeploymentInformation>
19 <Contents>
20 <File name="./CM_Constants.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
21 <File name="./Executor.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
22 <File name="./LSL_Constants.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
23 <File name="./LSL_Stub.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
24 <File name="./LS_Stub.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
25 <File name="./MOD_Stub.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
26 <File name="./OSSL_Stub.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
27 <File name="./ScriptBase.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
28 <File name="./ScriptSponsor.cs" subtype="Code" buildaction="Compile" dependson="" data="" />
29 </Contents>
30 <References>
31 <ProjectReference type="Assembly" refto="../../../../../../bin/log4net.dll" localcopy="False" />
32 <ProjectReference type="Assembly" refto="../../../../../../bin/Nini.dll" localcopy="False" />
33 <ProjectReference type="Assembly" refto="../../../../../../bin/Nini.dll" localcopy="False" />
34 <ProjectReference type="Assembly" refto="../../../../../../bin/OpenMetaverseTypes.dll" localcopy="False" />
35 <ProjectReference type="Project" localcopy="False" refto="OpenSim" />
36 <ProjectReference type="Project" localcopy="False" refto="OpenSim.Framework" />
37 <ProjectReference type="Project" localcopy="False" refto="OpenSim.Framework.Communications" />
38 <ProjectReference type="Project" localcopy="False" refto="OpenSim.Framework.Console" />
39 <ProjectReference type="Project" localcopy="False" refto="OpenSim.Region.CoreModules" />
40 <ProjectReference type="Project" localcopy="False" refto="OpenSim.Region.Framework" />
41 <ProjectReference type="Project" localcopy="False" refto="OpenSim.Region.ScriptEngine.Shared" />
42 <ProjectReference type="Assembly" refto="../../../../../../bin/RAIL.dll" localcopy="False" />
43 <ProjectReference type="Gac" localcopy="False" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
44 <ProjectReference type="Gac" localcopy="False" refto="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
45 <ProjectReference type="Gac" localcopy="False" refto="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
46 <ProjectReference type="Gac" localcopy="False" refto="System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
47 </References>
48</Project>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
index edbbc2a..b138da3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs
@@ -33,6 +33,7 @@ using System.Threading;
33using System.Reflection; 33using System.Reflection;
34using System.Collections; 34using System.Collections;
35using System.Collections.Generic; 35using System.Collections.Generic;
36using System.Diagnostics; //for [DebuggerNonUserCode]
36using OpenSim.Region.ScriptEngine.Interfaces; 37using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared; 38using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.Api.Runtime; 39using OpenSim.Region.ScriptEngine.Shared.Api.Runtime;
@@ -90,6 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
90 return (int)m_Executor.GetStateEventFlags(state); 91 return (int)m_Executor.GetStateEventFlags(state);
91 } 92 }
92 93
94 [DebuggerNonUserCode]
93 public void ExecuteEvent(string state, string FunctionName, object[] args) 95 public void ExecuteEvent(string state, string FunctionName, object[] args)
94 { 96 {
95 m_Executor.ExecuteEvent(state, FunctionName, args); 97 m_Executor.ExecuteEvent(state, FunctionName, args);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index e02d35e..e44a106 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -35,6 +35,7 @@ using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.CoreModules; 36using OpenSim.Region.CoreModules;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
38using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
39 40
40namespace OpenSim.Region.ScriptEngine.Shared 41namespace OpenSim.Region.ScriptEngine.Shared
@@ -120,6 +121,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
120 Type = 0; 121 Type = 0;
121 Velocity = new LSL_Types.Vector3(); 122 Velocity = new LSL_Types.Vector3();
122 initializeSurfaceTouch(); 123 initializeSurfaceTouch();
124 Country = String.Empty;
123 } 125 }
124 126
125 public UUID Key; 127 public UUID Key;
@@ -151,6 +153,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
151 private int touchFace; 153 private int touchFace;
152 public int TouchFace { get { return touchFace; } } 154 public int TouchFace { get { return touchFace; } }
153 155
156 public string Country;
157
154 // This can be done in two places including the constructor 158 // This can be done in two places including the constructor
155 // so be carefull what gets added here 159 // so be carefull what gets added here
156 private void initializeSurfaceTouch() 160 private void initializeSurfaceTouch()
@@ -198,6 +202,10 @@ namespace OpenSim.Region.ScriptEngine.Shared
198 return; 202 return;
199 203
200 Name = presence.Firstname + " " + presence.Lastname; 204 Name = presence.Firstname + " " + presence.Lastname;
205 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, Key);
206 if (account != null)
207 Country = account.UserCountry;
208
201 Owner = Key; 209 Owner = Key;
202 Position = new LSL_Types.Vector3(presence.AbsolutePosition); 210 Position = new LSL_Types.Vector3(presence.AbsolutePosition);
203 Rotation = new LSL_Types.Quaternion( 211 Rotation = new LSL_Types.Quaternion(
@@ -207,22 +215,27 @@ namespace OpenSim.Region.ScriptEngine.Shared
207 presence.Rotation.W); 215 presence.Rotation.W);
208 Velocity = new LSL_Types.Vector3(presence.Velocity); 216 Velocity = new LSL_Types.Vector3(presence.Velocity);
209 217
210 if (presence.PresenceType != PresenceType.Npc) 218 Type = 0x01; // Avatar
211 { 219 if (presence.PresenceType == PresenceType.Npc)
212 Type = AGENT; 220 Type = 0x20;
213 } 221
214 else 222 // Cope Impl. We don't use OS_NPC.
215 { 223 //if (presence.PresenceType != PresenceType.Npc)
216 Type = OS_NPC; 224 //{
217 225 // Type = AGENT;
218 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>(); 226 //}
219 INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); 227 //else
220 228 //{
221 if (npcData.SenseAsAgent) 229 // Type = OS_NPC;
222 { 230
223 Type |= AGENT; 231 // INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
224 } 232 // INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene);
225 } 233
234 // if (npcData.SenseAsAgent)
235 // {
236 // Type |= AGENT;
237 // }
238 //}
226 239
227 if (presence.Velocity != Vector3.Zero) 240 if (presence.Velocity != Vector3.Zero)
228 Type |= ACTIVE; 241 Type |= ACTIVE;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index fa6e6fc..674144b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -51,7 +51,8 @@ using OpenSim.Region.ScriptEngine.Shared.Api.Runtime;
51using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 51using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
52using OpenSim.Region.ScriptEngine.Shared.CodeTools; 52using OpenSim.Region.ScriptEngine.Shared.CodeTools;
53using OpenSim.Region.ScriptEngine.Interfaces; 53using OpenSim.Region.ScriptEngine.Interfaces;
54using System.Diagnostics; 54
55using System.Diagnostics; //for [DebuggerNonUserCode]
55 56
56namespace OpenSim.Region.ScriptEngine.Shared.Instance 57namespace OpenSim.Region.ScriptEngine.Shared.Instance
57{ 58{
@@ -256,8 +257,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
256 StartParam = startParam; 257 StartParam = startParam;
257 m_MaxScriptQueue = maxScriptQueue; 258 m_MaxScriptQueue = maxScriptQueue;
258 m_postOnRez = postOnRez; 259 m_postOnRez = postOnRez;
259 m_AttachedAvatar = Part.ParentGroup.AttachedAvatar; 260 m_AttachedAvatar = part.ParentGroup.AttachedAvatar;
260 m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID; 261 m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID;
261 262
262 m_SaveState = StatePersistedHere; 263 m_SaveState = StatePersistedHere;
263 264
@@ -456,27 +457,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
456 PostEvent(new EventParams("attach", 457 PostEvent(new EventParams("attach",
457 new object[] { new LSL_Types.LSLString(m_AttachedAvatar.ToString()) }, new DetectParams[0])); 458 new object[] { new LSL_Types.LSLString(m_AttachedAvatar.ToString()) }, new DetectParams[0]));
458 } 459 }
460
459 } 461 }
460 } 462 }
461 463
462 private void ReleaseControls() 464 private void ReleaseControls()
463 { 465 {
464 int permsMask; 466 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
465 UUID permsGranter; 467
466 lock (Part.TaskInventory) 468 if (part != null)
467 { 469 {
468 if (!Part.TaskInventory.ContainsKey(ItemID)) 470 int permsMask;
471 UUID permsGranter;
472 part.TaskInventory.LockItemsForRead(true);
473 if (!part.TaskInventory.ContainsKey(ItemID))
474 {
475 part.TaskInventory.LockItemsForRead(false);
469 return; 476 return;
477 }
478 permsGranter = part.TaskInventory[ItemID].PermsGranter;
479 permsMask = part.TaskInventory[ItemID].PermsMask;
480 part.TaskInventory.LockItemsForRead(false);
470 481
471 permsGranter = Part.TaskInventory[ItemID].PermsGranter; 482 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
472 permsMask = Part.TaskInventory[ItemID].PermsMask; 483 {
473 } 484 ScenePresence presence = Engine.World.GetScenePresence(permsGranter);
474 485 if (presence != null)
475 if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 486 presence.UnRegisterControlEventsToScript(LocalID, ItemID);
476 { 487 }
477 ScenePresence presence = Engine.World.GetScenePresence(permsGranter);
478 if (presence != null)
479 presence.UnRegisterControlEventsToScript(LocalID, ItemID);
480 } 488 }
481 } 489 }
482 490
@@ -639,6 +647,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
639 return true; 647 return true;
640 } 648 }
641 649
650 [DebuggerNonUserCode] //Prevents the debugger from farting in this function
642 public void SetState(string state) 651 public void SetState(string state)
643 { 652 {
644 if (state == State) 653 if (state == State)
@@ -764,6 +773,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
764 /// <returns></returns> 773 /// <returns></returns>
765 public object EventProcessor() 774 public object EventProcessor()
766 { 775 {
776 EventParams data = null;
767 // We check here as the thread stopping this instance from running may itself hold the m_Script lock. 777 // We check here as the thread stopping this instance from running may itself hold the m_Script lock.
768 if (!Running) 778 if (!Running)
769 return 0; 779 return 0;
@@ -850,7 +860,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
850 Part.ParentGroup.UUID, 860 Part.ParentGroup.UUID,
851 Part.AbsolutePosition, 861 Part.AbsolutePosition,
852 Part.ParentGroup.Scene.Name); 862 Part.ParentGroup.Scene.Name);
853
854 AsyncCommandManager.StateChange(Engine, 863 AsyncCommandManager.StateChange(Engine,
855 LocalID, ItemID); 864 LocalID, ItemID);
856 // we are effectively in the new state now, so we can resume queueing 865 // we are effectively in the new state now, so we can resume queueing
@@ -867,6 +876,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
867 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", 876 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
868 // PrimName, ScriptName, data.EventName, State); 877 // PrimName, ScriptName, data.EventName, State);
869 878
879
870 try 880 try
871 { 881 {
872 m_CurrentEvent = data.EventName; 882 m_CurrentEvent = data.EventName;
@@ -931,15 +941,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
931 catch (Exception) 941 catch (Exception)
932 { 942 {
933 } 943 }
934 // catch (Exception e2) // LEGIT: User Scripting
935 // {
936 // m_log.Error("[SCRIPT]: "+
937 // "Error displaying error in-world: " +
938 // e2.ToString());
939 // m_log.Error("[SCRIPT]: " +
940 // "Errormessage: Error compiling script:\r\n" +
941 // e.ToString());
942 // }
943 } 944 }
944 else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) 945 else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException))
945 { 946 {
@@ -1012,15 +1013,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1012 ReleaseControls(); 1013 ReleaseControls();
1013 1014
1014 Stop(timeout); 1015 Stop(timeout);
1015 Part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 1016 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
1016 Part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; 1017 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
1018 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
1019 part.CollisionSound = UUID.Zero;
1017 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); 1020 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID);
1021
1022 m_TimerQueued = false;
1023 m_StateChangeInProgress = false;
1018 EventQueue.Clear(); 1024 EventQueue.Clear();
1025
1019 m_Script.ResetVars(); 1026 m_Script.ResetVars();
1020 StartParam = 0; 1027 StartParam = 0;
1021 State = "default"; 1028 State = "default";
1022 1029
1023 Part.SetScriptEvents(ItemID, 1030
1031 part.SetScriptEvents(ItemID,
1024 (int)m_Script.GetStateEventFlags(State)); 1032 (int)m_Script.GetStateEventFlags(State));
1025 if (running) 1033 if (running)
1026 Start(); 1034 Start();
@@ -1031,6 +1039,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1031 new Object[0], new DetectParams[0])); 1039 new Object[0], new DetectParams[0]));
1032 } 1040 }
1033 1041
1042 [DebuggerNonUserCode] //Stops the VS debugger from farting in this function
1034 public void ApiResetScript() 1043 public void ApiResetScript()
1035 { 1044 {
1036 // bool running = Running; 1045 // bool running = Running;
@@ -1039,17 +1048,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1039 ReleaseControls(); 1048 ReleaseControls();
1040 1049
1041 m_Script.ResetVars(); 1050 m_Script.ResetVars();
1042 Part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 1051 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
1043 Part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; 1052 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
1053 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
1054 part.CollisionSound = UUID.Zero;
1044 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID); 1055 AsyncCommandManager.RemoveScript(Engine, LocalID, ItemID);
1045 1056
1057 m_TimerQueued = false;
1058 m_StateChangeInProgress = false;
1046 EventQueue.Clear(); 1059 EventQueue.Clear();
1047 m_Script.ResetVars(); 1060 m_Script.ResetVars();
1048 string oldState = State; 1061 string oldState = State;
1049 StartParam = 0; 1062 StartParam = 0;
1050 State = "default"; 1063 State = "default";
1051 1064
1052 Part.SetScriptEvents(ItemID, 1065 part.SetScriptEvents(ItemID,
1053 (int)m_Script.GetStateEventFlags(State)); 1066 (int)m_Script.GetStateEventFlags(State));
1054 1067
1055 if (m_CurrentEvent != "state_entry" || oldState != "default") 1068 if (m_CurrentEvent != "state_entry" || oldState != "default")
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index 0ca5ff3..d501979 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -100,21 +100,32 @@ namespace OpenSim.Region.ScriptEngine.Shared
100 100
101 #region Overriders 101 #region Overriders
102 102
103 public static implicit operator Boolean(Vector3 vec)
104 {
105 if (vec.x != 0)
106 return true;
107 if (vec.y != 0)
108 return true;
109 if (vec.z != 0)
110 return true;
111 return false;
112 }
113
103 public override string ToString() 114 public override string ToString()
104 { 115 {
105 string s=String.Format(Culture.FormatProvider,"<{0:0.000000},{1:0.000000},{2:0.000000}>", x, y, z); 116 string s = String.Format(Culture.FormatProvider, "<{0:0.000000}, {1:0.000000}, {2:0.000000}>", x, y, z);
106 return s; 117 return s;
107 } 118 }
108 119
109 public static explicit operator LSLString(Vector3 vec) 120 public static explicit operator LSLString(Vector3 vec)
110 { 121 {
111 string s=String.Format(Culture.FormatProvider,"<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); 122 string s = String.Format(Culture.FormatProvider, "<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z);
112 return new LSLString(s); 123 return new LSLString(s);
113 } 124 }
114 125
115 public static explicit operator string(Vector3 vec) 126 public static explicit operator string(Vector3 vec)
116 { 127 {
117 string s=String.Format(Culture.FormatProvider,"<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); 128 string s = String.Format(Culture.FormatProvider, "<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z);
118 return s; 129 return s;
119 } 130 }
120 131
@@ -397,6 +408,18 @@ namespace OpenSim.Region.ScriptEngine.Shared
397 #endregion 408 #endregion
398 409
399 #region Overriders 410 #region Overriders
411 public static implicit operator Boolean(Quaternion q)
412 {
413 if (q.x != 0)
414 return true;
415 if (q.y != 0)
416 return true;
417 if (q.z != 0)
418 return true;
419 if (q.s != 1.0f)
420 return true;
421 return false;
422 }
400 423
401 public override int GetHashCode() 424 public override int GetHashCode()
402 { 425 {
@@ -414,19 +437,19 @@ namespace OpenSim.Region.ScriptEngine.Shared
414 437
415 public override string ToString() 438 public override string ToString()
416 { 439 {
417 string st=String.Format(Culture.FormatProvider, "<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", x, y, z, s); 440 string st=String.Format(Culture.FormatProvider, "<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", x, y, z, s);
418 return st; 441 return st;
419 } 442 }
420 443
421 public static explicit operator string(Quaternion r) 444 public static explicit operator string(Quaternion r)
422 { 445 {
423 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); 446 string s=String.Format(Culture.FormatProvider,"<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s);
424 return s; 447 return s;
425 } 448 }
426 449
427 public static explicit operator LSLString(Quaternion r) 450 public static explicit operator LSLString(Quaternion r)
428 { 451 {
429 string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); 452 string s=String.Format(Culture.FormatProvider,"<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s);
430 return new LSLString(s); 453 return new LSLString(s);
431 } 454 }
432 455
@@ -537,7 +560,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
537 else if (o is LSL_Types.LSLFloat) 560 else if (o is LSL_Types.LSLFloat)
538 size += 8; 561 size += 8;
539 else if (o is LSL_Types.LSLString) 562 else if (o is LSL_Types.LSLString)
540 size += ((LSL_Types.LSLString)o).m_string.Length; 563 size += ((LSL_Types.LSLString)o).m_string == null ? 0 : ((LSL_Types.LSLString)o).m_string.Length;
541 else if (o is LSL_Types.key) 564 else if (o is LSL_Types.key)
542 size += ((LSL_Types.key)o).value.Length; 565 size += ((LSL_Types.key)o).value.Length;
543 else if (o is LSL_Types.Vector3) 566 else if (o is LSL_Types.Vector3)
@@ -546,6 +569,8 @@ namespace OpenSim.Region.ScriptEngine.Shared
546 size += 64; 569 size += 64;
547 else if (o is int) 570 else if (o is int)
548 size += 4; 571 size += 4;
572 else if (o is uint)
573 size += 4;
549 else if (o is string) 574 else if (o is string)
550 size += ((string)o).Length; 575 size += ((string)o).Length;
551 else if (o is float) 576 else if (o is float)
@@ -719,6 +744,11 @@ namespace OpenSim.Region.ScriptEngine.Shared
719 Data = tmp; 744 Data = tmp;
720 } 745 }
721 746
747 public static implicit operator Boolean(list l)
748 {
749 return l.Length != 0;
750 }
751
722 public static list operator +(list a, LSLString s) 752 public static list operator +(list a, LSLString s)
723 { 753 {
724 a.ExtendAndAdd(s); 754 a.ExtendAndAdd(s);
@@ -755,7 +785,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
755 int lb = -1; 785 int lb = -1;
756 try { la = a.Length; } 786 try { la = a.Length; }
757 catch (NullReferenceException) { } 787 catch (NullReferenceException) { }
758 try {lb = b.Length;} 788 try { lb = b.Length; }
759 catch (NullReferenceException) { } 789 catch (NullReferenceException) { }
760 790
761 return la != lb; 791 return la != lb;
@@ -1023,6 +1053,9 @@ namespace OpenSim.Region.ScriptEngine.Shared
1023 stride = 1; 1053 stride = 1;
1024 } 1054 }
1025 1055
1056 if ((Data.Length % stride) != 0)
1057 return new list(ret);
1058
1026 // we can optimize here in the case where stride == 1 and the list 1059 // we can optimize here in the case where stride == 1 and the list
1027 // consists of homogeneous types 1060 // consists of homogeneous types
1028 1061
@@ -1537,8 +1570,6 @@ namespace OpenSim.Region.ScriptEngine.Shared
1537 } 1570 }
1538 } 1571 }
1539 1572
1540
1541
1542 static public implicit operator String(LSLString s) 1573 static public implicit operator String(LSLString s)
1543 { 1574 {
1544 return s.m_string; 1575 return s.m_string;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 0ff2da3..ad775ff 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -245,6 +245,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
245 DetectParams d = new DetectParams(); 245 DetectParams d = new DetectParams();
246 d.Key =detobj.keyUUID; 246 d.Key =detobj.keyUUID;
247 d.Populate(myScriptEngine.World); 247 d.Populate(myScriptEngine.World);
248 d.LinkNum = detobj.linkNumber; // do it here since currently linknum is collided part
248 det.Add(d); 249 det.Add(d);
249 } 250 }
250 251
@@ -265,6 +266,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
265 DetectParams d = new DetectParams(); 266 DetectParams d = new DetectParams();
266 d.Key =detobj.keyUUID; 267 d.Key =detobj.keyUUID;
267 d.Populate(myScriptEngine.World); 268 d.Populate(myScriptEngine.World);
269 d.LinkNum = detobj.linkNumber; // do it here since currently linknum is collided part
268 det.Add(d); 270 det.Add(d);
269 } 271 }
270 272
@@ -284,6 +286,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
284 DetectParams d = new DetectParams(); 286 DetectParams d = new DetectParams();
285 d.Key =detobj.keyUUID; 287 d.Key =detobj.keyUUID;
286 d.Populate(myScriptEngine.World); 288 d.Populate(myScriptEngine.World);
289 d.LinkNum = detobj.linkNumber; // do it here since currently linknum is collided part
287 det.Add(d); 290 det.Add(d);
288 } 291 }
289 292
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs
index 2ef4058..07470d6 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEnginePersistenceTests.cs
@@ -43,6 +43,7 @@ using OpenSim.Tests.Common;
43 43
44namespace OpenSim.Region.ScriptEngine.Tests 44namespace OpenSim.Region.ScriptEngine.Tests
45{ 45{
46 /*
46 [TestFixture] 47 [TestFixture]
47 public class XEnginePersistenceTests : OpenSimTestCase 48 public class XEnginePersistenceTests : OpenSimTestCase
48 { 49 {
@@ -149,4 +150,5 @@ namespace OpenSim.Region.ScriptEngine.Tests
149 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo); 150 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo);
150 } 151 }
151 } 152 }
153 */
152} \ No newline at end of file 154} \ No newline at end of file
diff --git a/OpenSim/Server/Base/HttpServerBase.cs b/OpenSim/Server/Base/HttpServerBase.cs
index 44ef124..42a8c57 100644
--- a/OpenSim/Server/Base/HttpServerBase.cs
+++ b/OpenSim/Server/Base/HttpServerBase.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Server.Base
40{ 40{
41 public class HttpServerBase : ServicesServerBase 41 public class HttpServerBase : ServicesServerBase
42 { 42 {
43// private static readonly ILog m_Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 44
45 private uint m_consolePort; 45 private uint m_consolePort;
46 46
@@ -70,6 +70,7 @@ namespace OpenSim.Server.Base
70 70
71 bool ssl_main = networkConfig.GetBoolean("https_main",false); 71 bool ssl_main = networkConfig.GetBoolean("https_main",false);
72 bool ssl_listener = networkConfig.GetBoolean("https_listener",false); 72 bool ssl_listener = networkConfig.GetBoolean("https_listener",false);
73 bool ssl_external = networkConfig.GetBoolean("https_external",false);
73 74
74 m_consolePort = (uint)networkConfig.GetInt("ConsolePort", 0); 75 m_consolePort = (uint)networkConfig.GetInt("ConsolePort", 0);
75 76
@@ -115,21 +116,29 @@ namespace OpenSim.Server.Base
115 { 116 {
116 uint https_port = (uint)networkConfig.GetInt("https_port", 0); 117 uint https_port = (uint)networkConfig.GetInt("https_port", 0);
117 118
118 string cert_path = networkConfig.GetString("cert_path",String.Empty); 119 m_log.WarnFormat("[SSL]: External flag is {0}", ssl_external);
119 if (cert_path == String.Empty) 120 if (!ssl_external)
120 { 121 {
121 System.Console.WriteLine("ERROR: Path to X509 certificate is missing, server can't start."); 122 string cert_path = networkConfig.GetString("cert_path",String.Empty);
122 Environment.Exit(1); 123 if ( cert_path == String.Empty )
124 {
125 System.Console.WriteLine("Path to X509 certificate is missing, server can't start.");
126 Thread.CurrentThread.Abort();
127 }
128 string cert_pass = networkConfig.GetString("cert_pass",String.Empty);
129 if ( cert_pass == String.Empty )
130 {
131 System.Console.WriteLine("Password for X509 certificate is missing, server can't start.");
132 Thread.CurrentThread.Abort();
133 }
134
135 MainServer.AddHttpServer(new BaseHttpServer(https_port, ssl_listener, cert_path, cert_pass));
123 } 136 }
124 137 else
125 string cert_pass = networkConfig.GetString("cert_pass",String.Empty);
126 if (cert_pass == String.Empty)
127 { 138 {
128 System.Console.WriteLine("ERROR: Password for X509 certificate is missing, server can't start."); 139 m_log.WarnFormat("[SSL]: SSL port is active but no SSL is used because external SSL was requested.");
129 Environment.Exit(1); 140 MainServer.AddHttpServer(new BaseHttpServer(https_port));
130 } 141 }
131
132 MainServer.AddHttpServer(new BaseHttpServer(https_port, ssl_listener, cert_path, cert_pass));
133 } 142 }
134 } 143 }
135 144
diff --git a/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs b/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs
index e38543b..24f63d9 100644
--- a/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs
+++ b/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs
@@ -73,4 +73,4 @@ namespace OpenSim.Server.Handlers.BakedTextures
73 return new byte[0]; 73 return new byte[0];
74 } 74 }
75 } 75 }
76} \ No newline at end of file 76}
diff --git a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
index 9237c63..b63b594 100644
--- a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
@@ -185,6 +185,9 @@ namespace OpenSim.Server.Handlers.GridUser
185 185
186 GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(user); 186 GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(user);
187 187
188 if (guinfo == null)
189 return FailureResult();
190
188 Dictionary<string, object> result = new Dictionary<string, object>(); 191 Dictionary<string, object> result = new Dictionary<string, object>();
189 if (guinfo != null) 192 if (guinfo != null)
190 result["result"] = guinfo.ToKeyValuePairs(); 193 result["result"] = guinfo.ToKeyValuePairs();
diff --git a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
index 95a0510..f3d678f 100644
--- a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
@@ -62,7 +62,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
62 } 62 }
63 63
64 protected override bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination, 64 protected override bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination,
65 AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) 65 AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason)
66 { 66 {
67 return m_GatekeeperService.LoginAgent(source, aCircuit, destination, out reason); 67 return m_GatekeeperService.LoginAgent(source, aCircuit, destination, out reason);
68 } 68 }
diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
index e787f7c..367c481 100644
--- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
@@ -118,7 +118,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
118 118
119 119
120 protected override bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination, 120 protected override bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination,
121 AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) 121 AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason)
122 { 122 {
123 return m_UserAgentService.LoginAgentToGrid(source, aCircuit, gatekeeper, destination, fromLogin, out reason); 123 return m_UserAgentService.LoginAgentToGrid(source, aCircuit, gatekeeper, destination, fromLogin, out reason);
124 } 124 }
diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
index f2a5678..5d672c3 100644
--- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
+++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
@@ -132,8 +132,13 @@ namespace OpenSim.Server.Handlers.Login
132 132
133 //m_log.InfoFormat("[LOGIN]: XMLRPC Login Requested for {0} {1}, starting in {2}, using {3}", first, last, startLocation, clientVersion); 133 //m_log.InfoFormat("[LOGIN]: XMLRPC Login Requested for {0} {1}, starting in {2}, using {3}", first, last, startLocation, clientVersion);
134 134
135
136 bool LibOMVclient = false;
137 if (request.Params.Count > 4 && (string)request.Params[4] == "gridproxy")
138 LibOMVclient = true;
139
135 LoginResponse reply = null; 140 LoginResponse reply = null;
136 reply = m_LocalService.Login(first, last, passwd, startLocation, scopeID, clientVersion, channel, mac, id0, remoteClient); 141 reply = m_LocalService.Login(first, last, passwd, startLocation, scopeID, clientVersion, channel, mac, id0, remoteClient, LibOMVclient);
137 142
138 XmlRpcResponse response = new XmlRpcResponse(); 143 XmlRpcResponse response = new XmlRpcResponse();
139 response.Value = reply.ToHashtable(); 144 response.Value = reply.ToHashtable();
@@ -216,7 +221,7 @@ namespace OpenSim.Server.Handlers.Login
216 221
217 LoginResponse reply = null; 222 LoginResponse reply = null;
218 reply = m_LocalService.Login(map["first"].AsString(), map["last"].AsString(), map["passwd"].AsString(), startLocation, scopeID, 223 reply = m_LocalService.Login(map["first"].AsString(), map["last"].AsString(), map["passwd"].AsString(), startLocation, scopeID,
219 map["version"].AsString(), map["channel"].AsString(), map["mac"].AsString(), map["id0"].AsString(), remoteClient); 224 map["version"].AsString(), map["channel"].AsString(), map["mac"].AsString(), map["id0"].AsString(), remoteClient,false);
220 return reply.ToOSDMap(); 225 return reply.ToOSDMap();
221 226
222 } 227 }
@@ -259,7 +264,7 @@ namespace OpenSim.Server.Handlers.Login
259 (sender as WebSocketHttpServerHandler).GetRemoteIPEndpoint(); 264 (sender as WebSocketHttpServerHandler).GetRemoteIPEndpoint();
260 LoginResponse reply = null; 265 LoginResponse reply = null;
261 reply = m_LocalService.Login(first, last, passwd, start, scope, version, 266 reply = m_LocalService.Login(first, last, passwd, start, scope, version,
262 channel, mac, id0, endPoint); 267 channel, mac, id0, endPoint,false);
263 sock.SendMessage(OSDParser.SerializeJsonString(reply.ToOSDMap())); 268 sock.SendMessage(OSDParser.SerializeJsonString(reply.ToOSDMap()));
264 269
265 } 270 }
diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
index 649a27e..38dfffc 100644
--- a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
+++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
@@ -118,9 +118,13 @@ namespace OpenSim.Server.Handlers.MapImage
118 httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest; 118 httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest;
119 return FailureResult("Bad request."); 119 return FailureResult("Bad request.");
120 } 120 }
121 uint x = 0, y = 0; 121 int x = 0, y = 0;
122 UInt32.TryParse(request["X"].ToString(), out x); 122// UUID scopeID = new UUID("07f8d88e-cd5e-4239-a0ed-843f75d09992");
123 UInt32.TryParse(request["Y"].ToString(), out y); 123 UUID scopeID = UUID.Zero;
124 Int32.TryParse(request["X"].ToString(), out x);
125 Int32.TryParse(request["Y"].ToString(), out y);
126 if (request.ContainsKey("SCOPE"))
127 UUID.TryParse(request["SCOPE"].ToString(), out scopeID);
124 128
125 m_log.DebugFormat("[MAP ADD SERVER CONNECTOR]: Received map data for region at {0}-{1}", x, y); 129 m_log.DebugFormat("[MAP ADD SERVER CONNECTOR]: Received map data for region at {0}-{1}", x, y);
126 130
@@ -132,7 +136,7 @@ namespace OpenSim.Server.Handlers.MapImage
132 if (m_GridService != null) 136 if (m_GridService != null)
133 { 137 {
134 System.Net.IPAddress ipAddr = GetCallerIP(httpRequest); 138 System.Net.IPAddress ipAddr = GetCallerIP(httpRequest);
135 GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc(x), (int)Util.RegionToWorldLoc(y)); 139 GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y));
136 if (r != null) 140 if (r != null)
137 { 141 {
138 if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString()) 142 if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString())
@@ -153,7 +157,8 @@ namespace OpenSim.Server.Handlers.MapImage
153 byte[] data = Convert.FromBase64String(request["DATA"].ToString()); 157 byte[] data = Convert.FromBase64String(request["DATA"].ToString());
154 158
155 string reason = string.Empty; 159 string reason = string.Empty;
156 bool result = m_MapService.AddMapTile((int)x, (int)y, data, out reason); 160
161 bool result = m_MapService.AddMapTile((int)x, (int)y, data, scopeID, out reason);
157 162
158 if (result) 163 if (result)
159 return SuccessResult(); 164 return SuccessResult();
diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
index 7bb2f39..1ae669c 100644
--- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
+++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.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;
32 33
33using Nini.Config; 34using Nini.Config;
34using log4net; 35using log4net;
@@ -37,6 +38,7 @@ using OpenSim.Server.Base;
37using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
38using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
39using OpenSim.Server.Handlers.Base; 40using OpenSim.Server.Handlers.Base;
41using OpenMetaverse;
40 42
41namespace OpenSim.Server.Handlers.MapImage 43namespace OpenSim.Server.Handlers.MapImage
42{ 44{
@@ -70,6 +72,8 @@ namespace OpenSim.Server.Handlers.MapImage
70 72
71 class MapServerGetHandler : BaseStreamHandler 73 class MapServerGetHandler : BaseStreamHandler
72 { 74 {
75 public static ManualResetEvent ev = new ManualResetEvent(true);
76
73// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74 78
75 private IMapImageService m_MapService; 79 private IMapImageService m_MapService;
@@ -82,10 +86,25 @@ namespace OpenSim.Server.Handlers.MapImage
82 86
83 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 87 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
84 { 88 {
85 byte[] result = new byte[0]; 89 ev.WaitOne();
90 lock (ev)
91 {
92 ev.Reset();
93 }
86 94
95 byte[] result = new byte[0];
87 string format = string.Empty; 96 string format = string.Empty;
88 result = m_MapService.GetMapTile(path.Trim('/'), out format); 97
98// UUID scopeID = new UUID("07f8d88e-cd5e-4239-a0ed-843f75d09992");
99 UUID scopeID = UUID.Zero;
100
101 string[] bits = path.Trim('/').Split(new char[] {'/'});
102 if (bits.Length > 1)
103 {
104 scopeID = new UUID(bits[0]);
105 path = bits[1];
106 }
107 result = m_MapService.GetMapTile(path.Trim('/'), scopeID, out format);
89 if (result.Length > 0) 108 if (result.Length > 0)
90 { 109 {
91 httpResponse.StatusCode = (int)HttpStatusCode.OK; 110 httpResponse.StatusCode = (int)HttpStatusCode.OK;
@@ -100,6 +119,11 @@ namespace OpenSim.Server.Handlers.MapImage
100 httpResponse.ContentType = "text/plain"; 119 httpResponse.ContentType = "text/plain";
101 } 120 }
102 121
122 lock (ev)
123 {
124 ev.Set();
125 }
126
103 return result; 127 return result;
104 } 128 }
105 129
diff --git a/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs b/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs
new file mode 100644
index 0000000..4f8f7e1
--- /dev/null
+++ b/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs
@@ -0,0 +1,253 @@
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 Nini.Config;
35using log4net;
36using OpenMetaverse;
37
38using OpenSim.Framework;
39using OpenSim.Server.Base;
40using OpenSim.Services.Interfaces;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Server.Handlers.Base;
43
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45
46namespace OpenSim.Server.Handlers.MapImage
47{
48 public class MapRemoveServiceConnector : ServiceConnector
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private IMapImageService m_MapService;
53 private IGridService m_GridService;
54 private string m_ConfigName = "MapImageService";
55
56 public MapRemoveServiceConnector(IConfigSource config, IHttpServer server, string configName) :
57 base(config, server, configName)
58 {
59 IConfig serverConfig = config.Configs[m_ConfigName];
60 if (serverConfig == null)
61 throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
62
63 string mapService = serverConfig.GetString("LocalServiceModule",
64 String.Empty);
65
66 if (mapService == String.Empty)
67 throw new Exception("No LocalServiceModule in config file");
68
69 Object[] args = new Object[] { config };
70 m_MapService = ServerUtils.LoadPlugin<IMapImageService>(mapService, args);
71
72 string gridService = serverConfig.GetString("GridService", String.Empty);
73 if (gridService != string.Empty)
74 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
75
76 if (m_GridService != null)
77 m_log.InfoFormat("[MAP IMAGE HANDLER]: GridService check is ON");
78 else
79 m_log.InfoFormat("[MAP IMAGE HANDLER]: GridService check is OFF");
80
81 bool proxy = serverConfig.GetBoolean("HasProxy", false);
82 server.AddStreamHandler(new MapServerRemoveHandler(m_MapService, m_GridService, proxy));
83
84 }
85 }
86
87 class MapServerRemoveHandler : BaseStreamHandler
88 {
89 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
90 private IMapImageService m_MapService;
91 private IGridService m_GridService;
92 bool m_Proxy;
93
94 public MapServerRemoveHandler(IMapImageService service, IGridService grid, bool proxy) :
95 base("POST", "/removemap")
96 {
97 m_MapService = service;
98 m_GridService = grid;
99 m_Proxy = proxy;
100 }
101
102 public override byte[] Handle(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
103 {
104// m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path);
105 StreamReader sr = new StreamReader(requestData);
106 string body = sr.ReadToEnd();
107 sr.Close();
108 body = body.Trim();
109
110 try
111 {
112 Dictionary<string, object> request = ServerUtils.ParseQueryString(body);
113
114 if (!request.ContainsKey("X") || !request.ContainsKey("Y"))
115 {
116 httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest;
117 return FailureResult("Bad request.");
118 }
119 int x = 0, y = 0;
120 Int32.TryParse(request["X"].ToString(), out x);
121 Int32.TryParse(request["Y"].ToString(), out y);
122// UUID scopeID = new UUID("07f8d88e-cd5e-4239-a0ed-843f75d09992");
123 UUID scopeID = UUID.Zero;
124 if (request.ContainsKey("SCOPE"))
125 UUID.TryParse(request["SCOPE"].ToString(), out scopeID);
126
127 m_log.DebugFormat("[MAP REMOVE SERVER CONNECTOR]: Received position data for region at {0}-{1}", x, y);
128
129 if (m_GridService != null)
130 {
131 System.Net.IPAddress ipAddr = GetCallerIP(httpRequest);
132 GridRegion r = m_GridService.GetRegionByPosition(UUID.Zero, (int)Util.RegionToWorldLoc((uint)x), (int)Util.RegionToWorldLoc((uint)y));
133 if (r != null)
134 {
135 if (r.ExternalEndPoint.Address.ToString() != ipAddr.ToString())
136 {
137 m_log.WarnFormat("[MAP IMAGE HANDLER]: IP address {0} may be trying to impersonate region in IP {1}", ipAddr, r.ExternalEndPoint.Address);
138 return FailureResult("IP address of caller does not match IP address of registered region");
139 }
140
141 }
142 else
143 {
144 m_log.WarnFormat("[MAP IMAGE HANDLER]: IP address {0} may be rogue. Region not found at coordinates {1}-{2}",
145 ipAddr, x, y);
146 return FailureResult("Region not found at given coordinates");
147 }
148 }
149
150 string reason = string.Empty;
151 bool result = m_MapService.RemoveMapTile(x, y, scopeID, out reason);
152
153 if (result)
154 return SuccessResult();
155 else
156 return FailureResult(reason);
157
158 }
159 catch (Exception e)
160 {
161 m_log.ErrorFormat("[MAP SERVICE IMAGE HANDLER]: Exception {0} {1}", e.Message, e.StackTrace);
162 }
163
164 return FailureResult("Unexpected server error");
165 }
166
167 private byte[] SuccessResult()
168 {
169 XmlDocument doc = new XmlDocument();
170
171 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
172 "", "");
173
174 doc.AppendChild(xmlnode);
175
176 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
177 "");
178
179 doc.AppendChild(rootElement);
180
181 XmlElement result = doc.CreateElement("", "Result", "");
182 result.AppendChild(doc.CreateTextNode("Success"));
183
184 rootElement.AppendChild(result);
185
186 return DocToBytes(doc);
187 }
188
189 private byte[] FailureResult(string msg)
190 {
191 XmlDocument doc = new XmlDocument();
192
193 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
194 "", "");
195
196 doc.AppendChild(xmlnode);
197
198 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
199 "");
200
201 doc.AppendChild(rootElement);
202
203 XmlElement result = doc.CreateElement("", "Result", "");
204 result.AppendChild(doc.CreateTextNode("Failure"));
205
206 rootElement.AppendChild(result);
207
208 XmlElement message = doc.CreateElement("", "Message", "");
209 message.AppendChild(doc.CreateTextNode(msg));
210
211 rootElement.AppendChild(message);
212
213 return DocToBytes(doc);
214 }
215
216 private byte[] DocToBytes(XmlDocument doc)
217 {
218 MemoryStream ms = new MemoryStream();
219 XmlTextWriter xw = new XmlTextWriter(ms, null);
220 xw.Formatting = Formatting.Indented;
221 doc.WriteTo(xw);
222 xw.Flush();
223
224 return ms.ToArray();
225 }
226
227 private System.Net.IPAddress GetCallerIP(IOSHttpRequest request)
228 {
229 if (!m_Proxy)
230 return request.RemoteIPEndPoint.Address;
231
232 // We're behind a proxy
233 string xff = "X-Forwarded-For";
234 string xffValue = request.Headers[xff.ToLower()];
235 if (xffValue == null || (xffValue != null && xffValue == string.Empty))
236 xffValue = request.Headers[xff];
237
238 if (xffValue == null || (xffValue != null && xffValue == string.Empty))
239 {
240 m_log.WarnFormat("[MAP IMAGE HANDLER]: No XFF header");
241 return request.RemoteIPEndPoint.Address;
242 }
243
244 System.Net.IPEndPoint ep = Util.GetClientIPFromXFF(xffValue);
245 if (ep != null)
246 return ep.Address;
247
248 // Oops
249 return request.RemoteIPEndPoint.Address;
250 }
251
252 }
253}
diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs
index 49aa8ba..cac38f5 100644
--- a/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs
+++ b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs
@@ -433,6 +433,7 @@ namespace OpenSim.Server.Handlers
433 } 433 }
434 #endregion User Preferences 434 #endregion User Preferences
435 435
436
436 #region Utility 437 #region Utility
437 public bool AvatarImageAssetsRequest(OSDMap json, ref JsonRpcResponse response) 438 public bool AvatarImageAssetsRequest(OSDMap json, ref JsonRpcResponse response)
438 { 439 {
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
index 98c5312..c19421a 100644
--- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
@@ -120,6 +120,8 @@ namespace OpenSim.Server.Handlers.Simulation
120 120
121 protected virtual void DoQueryAccess(Hashtable request, Hashtable responsedata, UUID agentID, UUID regionID) 121 protected virtual void DoQueryAccess(Hashtable request, Hashtable responsedata, UUID agentID, UUID regionID)
122 { 122 {
123 EntityTransferContext ctx = new EntityTransferContext();
124
123 if (m_SimulationService == null) 125 if (m_SimulationService == null)
124 { 126 {
125 m_log.Debug("[AGENT HANDLER]: Agent QUERY called. Harmless but useless."); 127 m_log.Debug("[AGENT HANDLER]: Agent QUERY called. Harmless but useless.");
@@ -155,6 +157,9 @@ namespace OpenSim.Server.Handlers.Simulation
155 theirVersion = float.Parse(parts[1]); 157 theirVersion = float.Parse(parts[1]);
156 } 158 }
157 159
160 if (args.ContainsKey("context"))
161 ctx.Unpack((OSDMap)args["context"]);
162
158 // Decode the new versioning data 163 // Decode the new versioning data
159 float minVersionRequired = 0f; 164 float minVersionRequired = 0f;
160 float maxVersionRequired = 0f; 165 float maxVersionRequired = 0f;
@@ -245,7 +250,6 @@ namespace OpenSim.Server.Handlers.Simulation
245 250
246 string reason; 251 string reason;
247 // We're sending the version numbers down to the local connector to do the varregion check. 252 // We're sending the version numbers down to the local connector to do the varregion check.
248 EntityTransferContext ctx = new EntityTransferContext();
249 ctx.InboundVersion = inboundVersion; 253 ctx.InboundVersion = inboundVersion;
250 ctx.OutboundVersion = outboundVersion; 254 ctx.OutboundVersion = outboundVersion;
251 if (minVersionProvided == 0f) 255 if (minVersionProvided == 0f)
@@ -262,7 +266,6 @@ namespace OpenSim.Server.Handlers.Simulation
262 resp["version"] = OSD.FromString(legacyVersion); 266 resp["version"] = OSD.FromString(legacyVersion);
263 resp["negotiated_inbound_version"] = OSD.FromReal(inboundVersion); 267 resp["negotiated_inbound_version"] = OSD.FromReal(inboundVersion);
264 resp["negotiated_outbound_version"] = OSD.FromReal(outboundVersion); 268 resp["negotiated_outbound_version"] = OSD.FromReal(outboundVersion);
265 resp["variable_wearables_count_supported"] = OSD.FromBoolean(true);
266 269
267 OSDArray featuresWanted = new OSDArray(); 270 OSDArray featuresWanted = new OSDArray();
268 foreach (UUID feature in features) 271 foreach (UUID feature in features)
@@ -407,6 +410,8 @@ namespace OpenSim.Server.Handlers.Simulation
407 410
408 protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) 411 protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id)
409 { 412 {
413 EntityTransferContext ctx = new EntityTransferContext();
414
410 OSDMap args = Utils.GetOSDMap((string)request["body"]); 415 OSDMap args = Utils.GetOSDMap((string)request["body"]);
411 if (args == null) 416 if (args == null)
412 { 417 {
@@ -415,6 +420,9 @@ namespace OpenSim.Server.Handlers.Simulation
415 return; 420 return;
416 } 421 }
417 422
423 if (args.ContainsKey("context"))
424 ctx.Unpack((OSDMap)args["context"]);
425
418 AgentDestinationData data = CreateAgentDestinationData(); 426 AgentDestinationData data = CreateAgentDestinationData();
419 UnpackData(args, data, request); 427 UnpackData(args, data, request);
420 428
@@ -461,7 +469,8 @@ namespace OpenSim.Server.Handlers.Simulation
461 // This is the meaning of POST agent 469 // This is the meaning of POST agent
462 //m_regionClient.AdjustUserInformation(aCircuit); 470 //m_regionClient.AdjustUserInformation(aCircuit);
463 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); 471 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
464 bool result = CreateAgent(source, gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason); 472
473 bool result = CreateAgent(source, gatekeeper, destination, aCircuit, data.flags, data.fromLogin, ctx, out reason);
465 474
466 resp["reason"] = OSD.FromString(reason); 475 resp["reason"] = OSD.FromString(reason);
467 resp["success"] = OSD.FromBoolean(result); 476 resp["success"] = OSD.FromBoolean(result);
@@ -536,9 +545,29 @@ namespace OpenSim.Server.Handlers.Simulation
536 545
537 // subclasses can override this 546 // subclasses can override this
538 protected virtual bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination, 547 protected virtual bool CreateAgent(GridRegion source, GridRegion gatekeeper, GridRegion destination,
539 AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) 548 AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, EntityTransferContext ctx, out string reason)
540 { 549 {
541 return m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, out reason); 550 reason = String.Empty;
551 // The data and protocols are already defined so this is just a dummy to satisfy the interface
552 // TODO: make this end-to-end
553 if ((teleportFlags & (uint)TeleportFlags.ViaLogin) == 0)
554 {
555 Util.FireAndForget(x =>
556 {
557 string r;
558 m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out r);
559 m_log.DebugFormat("[AGENT HANDLER]: ASYNC CreateAgent {0}", r);
560 });
561
562 return true;
563 }
564 else
565 {
566
567 bool ret = m_SimulationService.CreateAgent(source, destination, aCircuit, teleportFlags, ctx, out reason);
568 m_log.DebugFormat("[AGENT HANDLER]: SYNC CreateAgent {0} {1}", ret.ToString(), reason);
569 return ret;
570 }
542 } 571 }
543 } 572 }
544 573
@@ -639,6 +668,9 @@ namespace OpenSim.Server.Handlers.Simulation
639 668
640 protected void DoAgentPut(Hashtable request, Hashtable responsedata) 669 protected void DoAgentPut(Hashtable request, Hashtable responsedata)
641 { 670 {
671 // TODO: Encode the ENtityTransferContext
672 EntityTransferContext ctx = new EntityTransferContext();
673
642 OSDMap args = Utils.GetOSDMap((string)request["body"]); 674 OSDMap args = Utils.GetOSDMap((string)request["body"]);
643 if (args == null) 675 if (args == null)
644 { 676 {
@@ -659,6 +691,8 @@ namespace OpenSim.Server.Handlers.Simulation
659 UUID.TryParse(args["destination_uuid"].AsString(), out uuid); 691 UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
660 if (args.ContainsKey("destination_name") && args["destination_name"] != null) 692 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
661 regionname = args["destination_name"].ToString(); 693 regionname = args["destination_name"].ToString();
694 if (args.ContainsKey("context"))
695 ctx.Unpack((OSDMap)args["context"]);
662 696
663 GridRegion destination = new GridRegion(); 697 GridRegion destination = new GridRegion();
664 destination.RegionID = uuid; 698 destination.RegionID = uuid;
@@ -681,7 +715,7 @@ namespace OpenSim.Server.Handlers.Simulation
681 AgentData agent = new AgentData(); 715 AgentData agent = new AgentData();
682 try 716 try
683 { 717 {
684 agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID)); 718 agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID), ctx);
685 } 719 }
686 catch (Exception ex) 720 catch (Exception ex)
687 { 721 {
@@ -700,7 +734,7 @@ namespace OpenSim.Server.Handlers.Simulation
700 AgentPosition agent = new AgentPosition(); 734 AgentPosition agent = new AgentPosition();
701 try 735 try
702 { 736 {
703 agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID)); 737 agent.Unpack(args, m_SimulationService.GetScene(destination.RegionID), ctx);
704 } 738 }
705 catch (Exception ex) 739 catch (Exception ex)
706 { 740 {
@@ -721,7 +755,10 @@ namespace OpenSim.Server.Handlers.Simulation
721 // subclasses can override this 755 // subclasses can override this
722 protected virtual bool UpdateAgent(GridRegion destination, AgentData agent) 756 protected virtual bool UpdateAgent(GridRegion destination, AgentData agent)
723 { 757 {
724 return m_SimulationService.UpdateAgent(destination, agent); 758 // The data and protocols are already defined so this is just a dummy to satisfy the interface
759 // TODO: make this end-to-end
760 EntityTransferContext ctx = new EntityTransferContext();
761 return m_SimulationService.UpdateAgent(destination, agent, ctx);
725 } 762 }
726 } 763 }
727 764
diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs
index 65e9287..ed5a481 100644
--- a/OpenSim/Server/ServerMain.cs
+++ b/OpenSim/Server/ServerMain.cs
@@ -29,6 +29,7 @@ using Nini.Config;
29using log4net; 29using log4net;
30using System.Reflection; 30using System.Reflection;
31using System; 31using System;
32using System.Net;
32using System.Collections.Generic; 33using System.Collections.Generic;
33using OpenSim.Framework.Servers; 34using OpenSim.Framework.Servers;
34using OpenSim.Framework.Servers.HttpServer; 35using OpenSim.Framework.Servers.HttpServer;
@@ -53,6 +54,10 @@ namespace OpenSim.Server
53 54
54 public static int Main(string[] args) 55 public static int Main(string[] args)
55 { 56 {
57 // Make sure we don't get outbound connections queueing
58 ServicePointManager.DefaultConnectionLimit = 50;
59 ServicePointManager.UseNagleAlgorithm = false;
60
56 m_Server = new HttpServerBase("R.O.B.U.S.T.", args); 61 m_Server = new HttpServerBase("R.O.B.U.S.T.", args);
57 62
58 string registryLocation; 63 string registryLocation;
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs
index 0aefa16..c57db48 100644
--- a/OpenSim/Services/AssetService/AssetService.cs
+++ b/OpenSim/Services/AssetService/AssetService.cs
@@ -174,7 +174,10 @@ namespace OpenSim.Services.AssetService
174 { 174 {
175// m_log.DebugFormat( 175// m_log.DebugFormat(
176// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length); 176// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length);
177 m_Database.StoreAsset(asset); 177 if (!m_Database.StoreAsset(asset))
178 {
179 return UUID.Zero.ToString();
180 }
178 } 181 }
179// else 182// else
180// { 183// {
diff --git a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
index 229f557..e42f9a0 100644
--- a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
+++ b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
@@ -30,10 +30,11 @@ using OpenMetaverse;
30using log4net; 30using log4net;
31using Nini.Config; 31using Nini.Config;
32using System.Reflection; 32using System.Reflection;
33using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces;
33using OpenSim.Data; 35using OpenSim.Data;
34using OpenSim.Framework; 36using OpenSim.Framework;
35using OpenSim.Services.Base; 37using OpenSim.Services.Base;
36using OpenSim.Services.Interfaces;
37 38
38namespace OpenSim.Services.AuthenticationService 39namespace OpenSim.Services.AuthenticationService
39{ 40{
@@ -50,6 +51,12 @@ namespace OpenSim.Services.AuthenticationService
50 MethodBase.GetCurrentMethod().DeclaringType); 51 MethodBase.GetCurrentMethod().DeclaringType);
51 52
52 protected IAuthenticationData m_Database; 53 protected IAuthenticationData m_Database;
54 protected IUserAccountService m_UserAccountService = null;
55
56 public AuthenticationServiceBase(IConfigSource config, IUserAccountService acct) : this(config)
57 {
58 m_UserAccountService = acct;
59 }
53 60
54 public AuthenticationServiceBase(IConfigSource config) : base(config) 61 public AuthenticationServiceBase(IConfigSource config) : base(config)
55 { 62 {
diff --git a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
index 5f1bde1..a069838 100644
--- a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
+++ b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
@@ -51,6 +51,12 @@ namespace OpenSim.Services.AuthenticationService
51 LogManager.GetLogger( 51 LogManager.GetLogger(
52 MethodBase.GetCurrentMethod().DeclaringType); 52 MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 public PasswordAuthenticationService(IConfigSource config, IUserAccountService userService) :
55 base(config, userService)
56 {
57 m_log.Debug("[AUTH SERVICE]: Started with User Account access");
58 }
59
54 public PasswordAuthenticationService(IConfigSource config) : 60 public PasswordAuthenticationService(IConfigSource config) :
55 base(config) 61 base(config)
56 { 62 {
@@ -58,42 +64,90 @@ namespace OpenSim.Services.AuthenticationService
58 64
59 public string Authenticate(UUID principalID, string password, int lifetime) 65 public string Authenticate(UUID principalID, string password, int lifetime)
60 { 66 {
67 UUID realID;
68 return Authenticate(principalID, password, lifetime, out realID);
69 }
70
71 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
72 {
73 realID = UUID.Zero;
74
75 m_log.DebugFormat("[AUTH SERVICE]: Authenticating for {0}, user account service present: {1}", principalID, m_UserAccountService != null);
61 AuthenticationData data = m_Database.Get(principalID); 76 AuthenticationData data = m_Database.Get(principalID);
77 UserAccount user = null;
78 if (m_UserAccountService != null)
79 user = m_UserAccountService.GetUserAccount(UUID.Zero, principalID);
62 80
63 if (data == null) 81 if (data == null || data.Data == null)
64 { 82 {
65 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} not found", principalID); 83 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID);
66 return String.Empty; 84 return String.Empty;
67 } 85 }
68 else if (data.Data == null) 86
87 if (!data.Data.ContainsKey("passwordHash") ||
88 !data.Data.ContainsKey("passwordSalt"))
69 { 89 {
70 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} data not found", principalID);
71 return String.Empty; 90 return String.Empty;
72 } 91 }
73 else if (!data.Data.ContainsKey("passwordHash") || !data.Data.ContainsKey("passwordSalt")) 92
93 string hashed = Util.Md5Hash(password + ":" +
94 data.Data["passwordSalt"].ToString());
95
96 m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString());
97
98 if (data.Data["passwordHash"].ToString() == hashed)
99 {
100 return GetToken(principalID, lifetime);
101 }
102
103 if (user == null)
74 { 104 {
75 m_log.DebugFormat( 105 m_log.DebugFormat("[PASS AUTH]: No user record for {0}", principalID);
76 "[AUTH SERVICE]: PrincipalID {0} data didn't contain either passwordHash or passwordSalt", principalID);
77 return String.Empty; 106 return String.Empty;
78 } 107 }
79 else 108
109 int impersonateFlag = 1 << 6;
110
111 if ((user.UserFlags & impersonateFlag) == 0)
112 return String.Empty;
113
114 m_log.DebugFormat("[PASS AUTH]: Attempting impersonation");
115
116 List<UserAccount> accounts = m_UserAccountService.GetUserAccountsWhere(UUID.Zero, "UserLevel >= 200");
117 if (accounts == null || accounts.Count == 0)
118 return String.Empty;
119
120 foreach (UserAccount a in accounts)
80 { 121 {
81 string hashed = Util.Md5Hash(password + ":" + data.Data["passwordSalt"].ToString()); 122 data = m_Database.Get(a.PrincipalID);
123 if (data == null || data.Data == null ||
124 !data.Data.ContainsKey("passwordHash") ||
125 !data.Data.ContainsKey("passwordSalt"))
126 {
127 continue;
128 }
129
130// m_log.DebugFormat("[PASS AUTH]: Trying {0}", data.PrincipalID);
82 131
83 m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString()); 132 hashed = Util.Md5Hash(password + ":" +
133 data.Data["passwordSalt"].ToString());
84 134
85 if (data.Data["passwordHash"].ToString() == hashed) 135 if (data.Data["passwordHash"].ToString() == hashed)
86 { 136 {
137 m_log.DebugFormat("[PASS AUTH]: {0} {1} impersonating {2}, proceeding with login", a.FirstName, a.LastName, principalID);
138 realID = a.PrincipalID;
87 return GetToken(principalID, lifetime); 139 return GetToken(principalID, lifetime);
88 } 140 }
89 else 141// else
90 { 142// {
91 m_log.DebugFormat( 143// m_log.DebugFormat(
92 "[AUTH SERVICE]: Salted hash {0} of given password did not match salted hash of {1} for PrincipalID {2}. Authentication failure.", 144// "[AUTH SERVICE]: Salted hash {0} of given password did not match salted hash of {1} for PrincipalID {2}. Authentication failure.",
93 hashed, data.Data["passwordHash"], principalID); 145// hashed, data.Data["passwordHash"], data.PrincipalID);
94 return String.Empty; 146// }
95 }
96 } 147 }
148
149 m_log.DebugFormat("[PASS AUTH]: Impersonation of {0} failed", principalID);
150 return String.Empty;
97 } 151 }
98 } 152 }
99} \ No newline at end of file 153}
diff --git a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
index 2344c0e..1510168 100644
--- a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
+++ b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
@@ -49,12 +49,23 @@ namespace OpenSim.Services.AuthenticationService
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
53 public WebkeyAuthenticationService(IConfigSource config, IUserAccountService userService) :
54 base(config, userService)
55 {
56 }
52 57
53 public WebkeyAuthenticationService(IConfigSource config) : 58 public WebkeyAuthenticationService(IConfigSource config) :
54 base(config) 59 base(config)
55 { 60 {
56 } 61 }
57 62
63 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
64 {
65 realID = UUID.Zero;
66 return Authenticate(principalID, password, lifetime);
67 }
68
58 public string Authenticate(UUID principalID, string password, int lifetime) 69 public string Authenticate(UUID principalID, string password, int lifetime)
59 { 70 {
60 if (new UUID(password) == UUID.Zero) 71 if (new UUID(password) == UUID.Zero)
diff --git a/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs
index 2c6cebd..bbc8470 100644
--- a/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs
+++ b/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs
@@ -55,14 +55,22 @@ namespace OpenSim.Services.AuthenticationService
55 55
56 public string Authenticate(UUID principalID, string password, int lifetime) 56 public string Authenticate(UUID principalID, string password, int lifetime)
57 { 57 {
58 UUID realID;
59
60 return Authenticate(principalID, password, lifetime, out realID);
61 }
62
63 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
64 {
58 AuthenticationData data = m_Database.Get(principalID); 65 AuthenticationData data = m_Database.Get(principalID);
59 string result = String.Empty; 66 string result = String.Empty;
67 realID = UUID.Zero;
60 if (data != null && data.Data != null) 68 if (data != null && data.Data != null)
61 { 69 {
62 if (data.Data.ContainsKey("webLoginKey")) 70 if (data.Data.ContainsKey("webLoginKey"))
63 { 71 {
64 m_log.DebugFormat("[AUTH SERVICE]: Attempting web key authentication for PrincipalID {0}", principalID); 72 m_log.DebugFormat("[AUTH SERVICE]: Attempting web key authentication for PrincipalID {0}", principalID);
65 result = m_svcChecks["web_login_key"].Authenticate(principalID, password, lifetime); 73 result = m_svcChecks["web_login_key"].Authenticate(principalID, password, lifetime, out realID);
66 if (result == String.Empty) 74 if (result == String.Empty)
67 { 75 {
68 m_log.DebugFormat("[AUTH SERVICE]: Web Login failed for PrincipalID {0}", principalID); 76 m_log.DebugFormat("[AUTH SERVICE]: Web Login failed for PrincipalID {0}", principalID);
@@ -71,12 +79,15 @@ namespace OpenSim.Services.AuthenticationService
71 if (result == string.Empty && data.Data.ContainsKey("passwordHash") && data.Data.ContainsKey("passwordSalt")) 79 if (result == string.Empty && data.Data.ContainsKey("passwordHash") && data.Data.ContainsKey("passwordSalt"))
72 { 80 {
73 m_log.DebugFormat("[AUTH SERVICE]: Attempting password authentication for PrincipalID {0}", principalID); 81 m_log.DebugFormat("[AUTH SERVICE]: Attempting password authentication for PrincipalID {0}", principalID);
74 result = m_svcChecks["password"].Authenticate(principalID, password, lifetime); 82 result = m_svcChecks["password"].Authenticate(principalID, password, lifetime, out realID);
75 if (result == String.Empty) 83 if (result == String.Empty)
76 { 84 {
77 m_log.DebugFormat("[AUTH SERVICE]: Password login failed for PrincipalID {0}", principalID); 85 m_log.DebugFormat("[AUTH SERVICE]: Password login failed for PrincipalID {0}", principalID);
78 } 86 }
79 } 87 }
88
89
90
80 if (result == string.Empty) 91 if (result == string.Empty)
81 { 92 {
82 m_log.DebugFormat("[AUTH SERVICE]: Both password and webLoginKey-based authentication failed for PrincipalID {0}", principalID); 93 m_log.DebugFormat("[AUTH SERVICE]: Both password and webLoginKey-based authentication failed for PrincipalID {0}", principalID);
@@ -86,7 +97,9 @@ namespace OpenSim.Services.AuthenticationService
86 { 97 {
87 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID); 98 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID);
88 } 99 }
100
101
89 return result; 102 return result;
90 } 103 }
91 } 104 }
92} \ No newline at end of file 105}
diff --git a/OpenSim/Services/Base/ServiceBase.cs b/OpenSim/Services/Base/ServiceBase.cs
index a7eb2be..c18226b 100644
--- a/OpenSim/Services/Base/ServiceBase.cs
+++ b/OpenSim/Services/Base/ServiceBase.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.IO;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.IO; 31using System.IO;
31using System.Reflection; 32using System.Reflection;
@@ -54,6 +55,7 @@ namespace OpenSim.Services.Base
54 string noRoot = dllName.Substring(pathRoot.Length); 55 string noRoot = dllName.Substring(pathRoot.Length);
55 string[] parts = noRoot.Split(new char[] {':'}); 56 string[] parts = noRoot.Split(new char[] {':'});
56 57
58
57 dllName = pathRoot + parts[0]; 59 dllName = pathRoot + parts[0];
58 60
59 string className = String.Empty; 61 string className = String.Empty;
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index bd43552..622780a 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -27,9 +27,11 @@
27 27
28using log4net; 28using log4net;
29using System; 29using System;
30using System.Threading;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.IO; 32using System.IO;
32using System.Reflection; 33using System.Reflection;
34using System.Timers;
33using Nini.Config; 35using Nini.Config;
34using OpenSim.Framework; 36using OpenSim.Framework;
35using OpenSim.Framework.Console; 37using OpenSim.Framework.Console;
@@ -46,13 +48,22 @@ namespace OpenSim.Services.Connectors
46 48
47 private string m_ServerURI = String.Empty; 49 private string m_ServerURI = String.Empty;
48 private IImprovedAssetCache m_Cache = null; 50 private IImprovedAssetCache m_Cache = null;
51 private int m_retryCounter;
52 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>();
53 private System.Timers.Timer m_retryTimer;
49 private int m_maxAssetRequestConcurrency = 30; 54 private int m_maxAssetRequestConcurrency = 30;
50 55
51 private delegate void AssetRetrievedEx(AssetBase asset); 56 private delegate void AssetRetrievedEx(AssetBase asset);
52 57
53 // Keeps track of concurrent requests for the same asset, so that it's only loaded once. 58 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
54 // Maps: Asset ID -> Handlers which will be called when the asset has been loaded 59 // Maps: Asset ID -> Handlers which will be called when the asset has been loaded
55 private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>(); 60// private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>();
61
62 private Dictionary<string, List<AssetRetrievedEx>> m_AssetHandlers = new Dictionary<string, List<AssetRetrievedEx>>();
63
64 private Dictionary<string, string> m_UriMap = new Dictionary<string, string>();
65
66 private Thread[] m_fetchThreads;
56 67
57 public int MaxAssetRequestConcurrency 68 public int MaxAssetRequestConcurrency
58 { 69 {
@@ -91,13 +102,113 @@ namespace OpenSim.Services.Connectors
91 string serviceURI = assetConfig.GetString("AssetServerURI", 102 string serviceURI = assetConfig.GetString("AssetServerURI",
92 String.Empty); 103 String.Empty);
93 104
105 m_ServerURI = serviceURI;
106
94 if (serviceURI == String.Empty) 107 if (serviceURI == String.Empty)
95 { 108 {
96 m_log.Error("[ASSET CONNECTOR]: No Server URI named in section AssetService"); 109 m_log.Error("[ASSET CONNECTOR]: No Server URI named in section AssetService");
97 throw new Exception("Asset connector init error"); 110 throw new Exception("Asset connector init error");
98 } 111 }
99 112
100 m_ServerURI = serviceURI; 113
114 m_retryTimer = new System.Timers.Timer();
115 m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck);
116 m_retryTimer.Interval = 60000;
117
118 Uri serverUri = new Uri(m_ServerURI);
119
120 string groupHost = serverUri.Host;
121
122 for (int i = 0 ; i < 256 ; i++)
123 {
124 string prefix = i.ToString("x2");
125 groupHost = assetConfig.GetString("AssetServerHost_"+prefix, groupHost);
126
127 m_UriMap[prefix] = groupHost;
128 //m_log.DebugFormat("[ASSET]: Using {0} for prefix {1}", groupHost, prefix);
129 }
130
131 m_fetchThreads = new Thread[2];
132
133 for (int i = 0 ; i < 2 ; i++)
134 {
135 m_fetchThreads[i] = new Thread(AssetRequestProcessor);
136 m_fetchThreads[i].Start();
137 }
138 }
139
140 private string MapServer(string id)
141 {
142 if (m_UriMap.Count == 0)
143 return m_ServerURI;
144
145 UriBuilder serverUri = new UriBuilder(m_ServerURI);
146
147 string prefix = id.Substring(0, 2).ToLower();
148
149 string host;
150
151 // HG URLs will not be valid UUIDS
152 if (m_UriMap.ContainsKey(prefix))
153 host = m_UriMap[prefix];
154 else
155 host = m_UriMap["00"];
156
157 serverUri.Host = host;
158
159 // m_log.DebugFormat("[ASSET]: Using {0} for host name for prefix {1}", host, prefix);
160
161 string ret = serverUri.Uri.AbsoluteUri;
162 if (ret.EndsWith("/"))
163 ret = ret.Substring(0, ret.Length - 1);
164 return ret;
165 }
166
167 protected void retryCheck(object source, ElapsedEventArgs e)
168 {
169 m_retryCounter++;
170 if (m_retryCounter > 60)
171 m_retryCounter -= 60;
172
173 List<int> keys = new List<int>();
174 foreach (int a in m_retryQueue.Keys)
175 {
176 keys.Add(a);
177 }
178 foreach (int a in keys)
179 {
180 //We exponentially fall back on frequency until we reach one attempt per hour
181 //The net result is that we end up in the queue for roughly 24 hours..
182 //24 hours worth of assets could be a lot, so the hope is that the region admin
183 //will have gotten the asset connector back online quickly!
184
185 int timefactor = a ^ 2;
186 if (timefactor > 60)
187 {
188 timefactor = 60;
189 }
190
191 //First, find out if we care about this timefactor
192 if (timefactor % a == 0)
193 {
194 //Yes, we do!
195 List<AssetBase> retrylist = m_retryQueue[a];
196 m_retryQueue.Remove(a);
197
198 foreach(AssetBase ass in retrylist)
199 {
200 Store(ass); //Store my ass. This function will put it back in the dictionary if it fails
201 }
202 }
203 }
204
205 if (m_retryQueue.Count == 0)
206 {
207 //It might only be one tick per minute, but I have
208 //repented and abandoned my wasteful ways
209 m_retryCounter = 0;
210 m_retryTimer.Stop();
211 }
101 } 212 }
102 213
103 protected void SetCache(IImprovedAssetCache cache) 214 protected void SetCache(IImprovedAssetCache cache)
@@ -107,15 +218,13 @@ namespace OpenSim.Services.Connectors
107 218
108 public AssetBase Get(string id) 219 public AssetBase Get(string id)
109 { 220 {
110// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Synchronous get request for {0}", id); 221 string uri = MapServer(id) + "/assets/" + id;
111
112 string uri = m_ServerURI + "/assets/" + id;
113 222
114 AssetBase asset = null; 223 AssetBase asset = null;
115 if (m_Cache != null) 224 if (m_Cache != null)
116 asset = m_Cache.Get(id); 225 asset = m_Cache.Get(id);
117 226
118 if (asset == null) 227 if (asset == null || asset.Data == null || asset.Data.Length == 0)
119 { 228 {
120 // XXX: Commented out for now since this has either never been properly operational or not for some time 229 // XXX: Commented out for now since this has either never been properly operational or not for some time
121 // as m_maxAssetRequestConcurrency was being passed as the timeout, not a concurrency limiting option. 230 // as m_maxAssetRequestConcurrency was being passed as the timeout, not a concurrency limiting option.
@@ -154,7 +263,7 @@ namespace OpenSim.Services.Connectors
154 return fullAsset.Metadata; 263 return fullAsset.Metadata;
155 } 264 }
156 265
157 string uri = m_ServerURI + "/assets/" + id + "/metadata"; 266 string uri = MapServer(id) + "/assets/" + id + "/metadata";
158 267
159 AssetMetadata asset = SynchronousRestObjectRequester.MakeRequest<int, AssetMetadata>("GET", uri, 0, m_Auth); 268 AssetMetadata asset = SynchronousRestObjectRequester.MakeRequest<int, AssetMetadata>("GET", uri, 0, m_Auth);
160 return asset; 269 return asset;
@@ -170,7 +279,7 @@ namespace OpenSim.Services.Connectors
170 return fullAsset.Data; 279 return fullAsset.Data;
171 } 280 }
172 281
173 using (RestClient rc = new RestClient(m_ServerURI)) 282 using (RestClient rc = new RestClient(MapServer(id)))
174 { 283 {
175 rc.AddResourcePath("assets"); 284 rc.AddResourcePath("assets");
176 rc.AddResourcePath(id); 285 rc.AddResourcePath(id);
@@ -178,83 +287,136 @@ namespace OpenSim.Services.Connectors
178 287
179 rc.RequestMethod = "GET"; 288 rc.RequestMethod = "GET";
180 289
181 Stream s = rc.Request(m_Auth); 290 using (Stream s = rc.Request(m_Auth))
182
183 if (s == null)
184 return null;
185
186 if (s.Length > 0)
187 { 291 {
188 byte[] ret = new byte[s.Length]; 292 if (s == null)
189 s.Read(ret, 0, (int)s.Length); 293 return null;
190 294
191 return ret; 295 if (s.Length > 0)
192 } 296 {
297 byte[] ret = new byte[s.Length];
298 s.Read(ret, 0, (int)s.Length);
193 299
300 return ret;
301 }
302 }
194 return null; 303 return null;
195 } 304 }
196 } 305 }
197 306
198 public bool Get(string id, Object sender, AssetRetrieved handler) 307 private class QueuedAssetRequest
199 { 308 {
200// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Potentially asynchronous get request for {0}", id); 309 public string uri;
310 public string id;
311 }
201 312
202 string uri = m_ServerURI + "/assets/" + id; 313 private OpenMetaverse.BlockingQueue<QueuedAssetRequest> m_requestQueue =
314 new OpenMetaverse.BlockingQueue<QueuedAssetRequest>();
203 315
204 AssetBase asset = null; 316 private void AssetRequestProcessor()
205 if (m_Cache != null) 317 {
206 asset = m_Cache.Get(id); 318 QueuedAssetRequest r;
207 319
208 if (asset == null) 320 while (true)
209 { 321 {
210 lock (m_AssetHandlers) 322 r = m_requestQueue.Dequeue();
211 {
212 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
213 323
214 AssetRetrievedEx handlers; 324 string uri = r.uri;
215 if (m_AssetHandlers.TryGetValue(id, out handlers)) 325 string id = r.id;
216 {
217 // Someone else is already loading this asset. It will notify our handler when done.
218 handlers += handlerEx;
219 return true;
220 }
221
222 // Load the asset ourselves
223 handlers += handlerEx;
224 m_AssetHandlers.Add(id, handlers);
225 }
226 326
227 bool success = false; 327 bool success = false;
228 try 328 try
229 { 329 {
230 AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, 330 AssetBase a = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, 30000, m_Auth);
231 delegate(AssetBase a) 331 if (a != null)
332 {
333 if (m_Cache != null)
334 m_Cache.Cache(a);
335
336 List<AssetRetrievedEx> handlers;
337 lock (m_AssetHandlers)
232 { 338 {
233 if (a != null && m_Cache != null) 339 handlers = m_AssetHandlers[id];
234 m_Cache.Cache(a); 340 m_AssetHandlers.Remove(id);
341 }
235 342
236 AssetRetrievedEx handlers; 343 Util.FireAndForget(x =>
237 lock (m_AssetHandlers)
238 { 344 {
239 handlers = m_AssetHandlers[id]; 345
240 m_AssetHandlers.Remove(id); 346 foreach (AssetRetrievedEx h in handlers)
241 } 347 {
242 handlers.Invoke(a); 348 // Util.FireAndForget(x =>
243 }, m_maxAssetRequestConcurrency, m_Auth); 349 // {
244 350 try { h.Invoke(a); }
245 success = true; 351 catch { }
352 // });
353 }
354
355 if (handlers != null)
356 handlers.Clear();
357
358 });
359
360// if (handlers != null)
361// handlers.Clear();
362 success = true;
363 }
246 } 364 }
247 finally 365 finally
248 { 366 {
249 if (!success) 367 if (!success)
250 { 368 {
369 List<AssetRetrievedEx> handlers;
251 lock (m_AssetHandlers) 370 lock (m_AssetHandlers)
252 { 371 {
372 handlers = m_AssetHandlers[id];
253 m_AssetHandlers.Remove(id); 373 m_AssetHandlers.Remove(id);
254 } 374 }
375 if (handlers != null)
376 handlers.Clear();
255 } 377 }
256 } 378 }
257 } 379 }
380 }
381
382 public bool Get(string id, Object sender, AssetRetrieved handler)
383 {
384 string uri = MapServer(id) + "/assets/" + id;
385
386 AssetBase asset = null;
387 if (m_Cache != null)
388 asset = m_Cache.Get(id);
389
390 if (asset == null || asset.Data == null || asset.Data.Length == 0)
391 {
392 lock (m_AssetHandlers)
393 {
394 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
395
396// AssetRetrievedEx handlers;
397 List<AssetRetrievedEx> handlers;
398 if (m_AssetHandlers.TryGetValue(id, out handlers))
399 {
400 // Someone else is already loading this asset. It will notify our handler when done.
401// handlers += handlerEx;
402 handlers.Add(handlerEx);
403 return true;
404 }
405
406 // Load the asset ourselves
407// handlers += handlerEx;
408 handlers = new List<AssetRetrievedEx>();
409 handlers.Add(handlerEx);
410
411 m_AssetHandlers.Add(id, handlers);
412 }
413
414 QueuedAssetRequest request = new QueuedAssetRequest();
415 request.id = id;
416 request.uri = uri;
417
418 m_requestQueue.Enqueue(request);
419 }
258 else 420 else
259 { 421 {
260 handler(id, sender, asset); 422 handler(id, sender, asset);
@@ -286,43 +448,95 @@ namespace OpenSim.Services.Connectors
286 448
287 public string Store(AssetBase asset) 449 public string Store(AssetBase asset)
288 { 450 {
289 if (asset.Local) 451 // Have to assign the asset ID here. This isn't likely to
452 // trigger since current callers don't pass emtpy IDs
453 // We need the asset ID to route the request to the proper
454 // cluster member, so we can't have the server assign one.
455 if (asset.ID == string.Empty)
290 { 456 {
291 if (m_Cache != null) 457 if (asset.FullID == UUID.Zero)
292 m_Cache.Cache(asset); 458 {
459 asset.FullID = UUID.Random();
460 }
461 asset.ID = asset.FullID.ToString();
462 }
463 else if (asset.FullID == UUID.Zero)
464 {
465 UUID uuid = UUID.Zero;
466 if (UUID.TryParse(asset.ID, out uuid))
467 {
468 asset.FullID = uuid;
469 }
470 else
471 {
472 asset.FullID = UUID.Random();
473 }
474 }
293 475
476 if (m_Cache != null)
477 m_Cache.Cache(asset);
478 if (asset.Temporary || asset.Local)
479 {
294 return asset.ID; 480 return asset.ID;
295 } 481 }
296 482
297 string uri = m_ServerURI + "/assets/"; 483 string uri = MapServer(asset.FullID.ToString()) + "/assets/";
298 484
299 string newID; 485 string newID;
300 try 486 try
301 { 487 {
302 newID = SynchronousRestObjectRequester.MakeRequest<AssetBase, string>("POST", uri, asset, m_Auth); 488 newID = SynchronousRestObjectRequester.
489 MakeRequest<AssetBase, string>("POST", uri, asset, 100000, m_Auth);
490 if (newID == null || newID == "")
491 {
492 newID = UUID.Zero.ToString();
493 }
303 } 494 }
304 catch (Exception e) 495 catch (Exception e)
305 { 496 {
306 m_log.Warn(string.Format("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1} ", asset.ID, e.Message), e); 497 newID = UUID.Zero.ToString();
307 return string.Empty;
308 } 498 }
309 499
310 // TEMPORARY: SRAS returns 'null' when it's asked to store existing assets 500 if (newID == UUID.Zero.ToString())
311 if (newID == null)
312 { 501 {
313 m_log.DebugFormat("[ASSET CONNECTOR]: Storing of asset {0} returned null; assuming the asset already exists", asset.ID); 502 //The asset upload failed, put it in a queue for later
314 return asset.ID; 503 asset.UploadAttempts++;
504 if (asset.UploadAttempts > 30)
505 {
506 //By this stage we've been in the queue for a good few hours;
507 //We're going to drop the asset.
508 m_log.ErrorFormat("[Assets] Dropping asset {0} - Upload has been in the queue for too long.", asset.ID.ToString());
509 }
510 else
511 {
512 if (!m_retryQueue.ContainsKey(asset.UploadAttempts))
513 {
514 m_retryQueue.Add(asset.UploadAttempts, new List<AssetBase>());
515 }
516 List<AssetBase> m_queue = m_retryQueue[asset.UploadAttempts];
517 m_queue.Add(asset);
518 m_log.WarnFormat("[Assets] Upload failed: {0} - Requeuing asset for another run.", asset.ID.ToString());
519 m_retryTimer.Start();
520 }
315 } 521 }
522 else
523 {
524 if (asset.UploadAttempts > 0)
525 {
526 m_log.InfoFormat("[Assets] Upload of {0} succeeded after {1} failed attempts", asset.ID.ToString(), asset.UploadAttempts.ToString());
527 }
528 if (newID != String.Empty)
529 {
530 // Placing this here, so that this work with old asset servers that don't send any reply back
531 // SynchronousRestObjectRequester returns somethins that is not an empty string
532 if (newID != null)
533 asset.ID = newID;
316 534
317 if (string.IsNullOrEmpty(newID)) 535 if (m_Cache != null)
318 return string.Empty; 536 m_Cache.Cache(asset);
319 537 }
320 asset.ID = newID; 538 }
321 539 return asset.ID;
322 if (m_Cache != null)
323 m_Cache.Cache(asset);
324
325 return newID;
326 } 540 }
327 541
328 public bool UpdateContent(string id, byte[] data) 542 public bool UpdateContent(string id, byte[] data)
@@ -343,7 +557,7 @@ namespace OpenSim.Services.Connectors
343 } 557 }
344 asset.Data = data; 558 asset.Data = data;
345 559
346 string uri = m_ServerURI + "/assets/" + id; 560 string uri = MapServer(id) + "/assets/" + id;
347 561
348 if (SynchronousRestObjectRequester.MakeRequest<AssetBase, bool>("POST", uri, asset, m_Auth)) 562 if (SynchronousRestObjectRequester.MakeRequest<AssetBase, bool>("POST", uri, asset, m_Auth))
349 { 563 {
@@ -357,7 +571,7 @@ namespace OpenSim.Services.Connectors
357 571
358 public bool Delete(string id) 572 public bool Delete(string id)
359 { 573 {
360 string uri = m_ServerURI + "/assets/" + id; 574 string uri = MapServer(id) + "/assets/" + id;
361 575
362 if (SynchronousRestObjectRequester.MakeRequest<int, bool>("DELETE", uri, 0, m_Auth)) 576 if (SynchronousRestObjectRequester.MakeRequest<int, bool>("DELETE", uri, 0, m_Auth))
363 { 577 {
diff --git a/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs b/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs
index c8a4912..0443f5a 100644
--- a/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs
@@ -84,6 +84,13 @@ namespace OpenSim.Services.Connectors
84 base.Initialise(source, "AuthenticationService"); 84 base.Initialise(source, "AuthenticationService");
85 } 85 }
86 86
87 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
88 {
89 realID = UUID.Zero;
90
91 return Authenticate(principalID, password, lifetime);
92 }
93
87 public string Authenticate(UUID principalID, string password, int lifetime) 94 public string Authenticate(UUID principalID, string password, int lifetime)
88 { 95 {
89 Dictionary<string, object> sendData = new Dictionary<string, object>(); 96 Dictionary<string, object> sendData = new Dictionary<string, object>();
diff --git a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
index 6d5ce4b..45f4514 100644
--- a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
+++ b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
@@ -144,44 +144,48 @@ namespace OpenSim.Services.Connectors.Friends
144 144
145 private bool Call(GridRegion region, Dictionary<string, object> sendData) 145 private bool Call(GridRegion region, Dictionary<string, object> sendData)
146 { 146 {
147 string reqString = ServerUtils.BuildQueryString(sendData); 147 Util.FireAndForget(x => {
148 //m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: queryString = {0}", reqString); 148 string reqString = ServerUtils.BuildQueryString(sendData);
149 if (region == null) 149 //m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: queryString = {0}", reqString);
150 return false; 150 if (region == null)
151 151 return;
152 string path = ServicePath(); 152
153 if (!region.ServerURI.EndsWith("/")) 153 string path = ServicePath();
154 path = "/" + path; 154 if (!region.ServerURI.EndsWith("/"))
155 string uri = region.ServerURI + path; 155 path = "/" + path;
156// m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri); 156 string uri = region.ServerURI + path;
157 157 // m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri);
158 try 158
159 { 159 try
160 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString);
161 if (reply != string.Empty)
162 { 160 {
163 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply); 161 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString);
164 162 if (reply != string.Empty)
165 if (replyData.ContainsKey("RESULT"))
166 { 163 {
167 if (replyData["RESULT"].ToString().ToLower() == "true") 164 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
168 return true; 165
166 if (replyData.ContainsKey("RESULT"))
167 {
168// if (replyData["RESULT"].ToString().ToLower() == "true")
169// return;
170// else
171 return;
172 }
169 else 173 else
170 return false; 174 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: reply data does not contain result field");
175
171 } 176 }
172 else 177 else
173 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: reply data does not contain result field"); 178 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: received empty reply");
174 179 }
180 catch (Exception e)
181 {
182 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: Exception when contacting remote sim at {0}: {1}", uri, e.Message);
175 } 183 }
176 else 184
177 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: received empty reply"); 185 return;
178 } 186 });
179 catch (Exception e) 187
180 { 188 return true;
181 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: Exception when contacting remote sim at {0}: {1}", uri, e.Message);
182 }
183
184 return false;
185 } 189 }
186 } 190 }
187} 191}
diff --git a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
index 596f867..6c6ccf9 100644
--- a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
@@ -49,6 +49,9 @@ namespace OpenSim.Services.Connectors
49 49
50 private string m_ServerURI = String.Empty; 50 private string m_ServerURI = String.Empty;
51 51
52 private ExpiringCache<ulong, GridRegion> m_regionCache =
53 new ExpiringCache<ulong, GridRegion>();
54
52 public GridServicesConnector() 55 public GridServicesConnector()
53 { 56 {
54 } 57 }
@@ -275,6 +278,11 @@ namespace OpenSim.Services.Connectors
275 278
276 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 279 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
277 { 280 {
281 ulong regionHandle = Util.UIntsToLong((uint)x, (uint)y);
282
283 if (m_regionCache.Contains(regionHandle))
284 return (GridRegion)m_regionCache[regionHandle];
285
278 Dictionary<string, object> sendData = new Dictionary<string, object>(); 286 Dictionary<string, object> sendData = new Dictionary<string, object>();
279 287
280 sendData["SCOPEID"] = scopeID.ToString(); 288 sendData["SCOPEID"] = scopeID.ToString();
@@ -316,6 +324,8 @@ namespace OpenSim.Services.Connectors
316 else 324 else
317 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition received null reply"); 325 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition received null reply");
318 326
327 m_regionCache.Add(regionHandle, rinfo, TimeSpan.FromSeconds(600));
328
319 return rinfo; 329 return rinfo;
320 } 330 }
321 331
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
index b1663ee..2340998 100644
--- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -161,6 +161,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
161 try 161 try
162 { 162 {
163 WebClient c = new WebClient(); 163 WebClient c = new WebClient();
164 //m_log.Debug("JPEG: " + imageURL);
164 string name = regionID.ToString(); 165 string name = regionID.ToString();
165 filename = Path.Combine(storagePath, name + ".jpg"); 166 filename = Path.Combine(storagePath, name + ".jpg");
166 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: Map image at {0}, cached at {1}", imageURL, filename); 167 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: Map image at {0}, cached at {1}", imageURL, filename);
@@ -189,11 +190,10 @@ namespace OpenSim.Services.Connectors.Hypergrid
189 190
190 ass.Data = imageData; 191 ass.Data = imageData;
191 192
192 mapTile = ass.FullID;
193
194 // finally
195 m_AssetService.Store(ass); 193 m_AssetService.Store(ass);
196 194
195 // finally
196 mapTile = ass.FullID;
197 } 197 }
198 catch // LEGIT: Catching problems caused by OpenJPEG p/invoke 198 catch // LEGIT: Catching problems caused by OpenJPEG p/invoke
199 { 199 {
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
index 8abd046..1dcc82a 100644
--- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -138,7 +138,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
138 Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI); 138 Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI);
139 139
140 uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome; 140 uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
141 return CreateAgent(source, home, aCircuit, flags, out reason); 141 EntityTransferContext ctx = new EntityTransferContext();
142 return CreateAgent(source, home, aCircuit, flags, ctx, out reason);
142 } 143 }
143 144
144 145
diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
index 7cecd93..c7d658a 100644
--- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
@@ -559,6 +559,7 @@ namespace OpenSim.Services.Connectors
559 List<UUID> pending = new List<UUID>(); 559 List<UUID> pending = new List<UUID>();
560 InventoryItemBase item = null; 560 InventoryItemBase item = null;
561 int i = 0; 561 int i = 0;
562
562 foreach (UUID id in itemIDs) 563 foreach (UUID id in itemIDs)
563 { 564 {
564 if (m_ItemCache.TryGetValue(id, out item)) 565 if (m_ItemCache.TryGetValue(id, out item))
diff --git a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs
index 034c42e..7839a68 100644
--- a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs
@@ -130,4 +130,4 @@ namespace OpenSim.Services.Connectors
130 return landData; 130 return landData;
131 } 131 }
132 } 132 }
133} \ No newline at end of file 133}
diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs
index c91ed84..84c4efe 100644
--- a/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs
+++ b/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs
@@ -149,13 +149,75 @@ namespace OpenSim.Services.Connectors
149 return false; 149 return false;
150 } 150 }
151 151
152 public bool AddMapTile(int x, int y, byte[] jpgData, out string reason) 152 public bool RemoveMapTile(int x, int y, UUID scopeID, out string reason)
153 { 153 {
154 reason = string.Empty; 154 reason = string.Empty;
155 int tickstart = Util.EnvironmentTickCount(); 155 int tickstart = Util.EnvironmentTickCount();
156 Dictionary<string, object> sendData = new Dictionary<string, object>(); 156 Dictionary<string, object> sendData = new Dictionary<string, object>();
157 sendData["X"] = x.ToString(); 157 sendData["X"] = x.ToString();
158 sendData["Y"] = y.ToString(); 158 sendData["Y"] = y.ToString();
159 sendData["SCOPE"] = scopeID.ToString();
160
161 string reqString = ServerUtils.BuildQueryString(sendData);
162 string uri = m_ServerURI + "/removemap";
163
164 try
165 {
166 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
167 uri,
168 reqString);
169 if (reply != string.Empty)
170 {
171 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
172
173 if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success"))
174 {
175 return true;
176 }
177 else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure"))
178 {
179 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Delete failed: {0}", replyData["Message"].ToString());
180 reason = replyData["Message"].ToString();
181 return false;
182 }
183 else if (!replyData.ContainsKey("Result"))
184 {
185 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: reply data does not contain result field");
186 }
187 else
188 {
189 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: unexpected result {0}", replyData["Result"].ToString());
190 reason = "Unexpected result " + replyData["Result"].ToString();
191 }
192
193 }
194 else
195 {
196 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Map post received null reply");
197 }
198 }
199 catch (Exception e)
200 {
201 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Exception when contacting map server at {0}: {1}", uri, e.Message);
202 }
203 finally
204 {
205 // This just dumps a warning for any operation that takes more than 100 ms
206 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
207 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile deleted in {0}ms", tickdiff);
208 }
209
210 return false;
211 }
212
213 public bool AddMapTile(int x, int y, byte[] jpgData, UUID scopeID, out string reason)
214 {
215 reason = string.Empty;
216 int tickstart = Util.EnvironmentTickCount();
217 Dictionary<string, object> sendData = new Dictionary<string, object>();
218 sendData["X"] = x.ToString();
219 sendData["Y"] = y.ToString();
220 sendData["SCOPE"] = scopeID.ToString();
159 sendData["TYPE"] = "image/jpeg"; 221 sendData["TYPE"] = "image/jpeg";
160 sendData["DATA"] = Convert.ToBase64String(jpgData); 222 sendData["DATA"] = Convert.ToBase64String(jpgData);
161 223
@@ -216,7 +278,7 @@ namespace OpenSim.Services.Connectors
216 278
217 } 279 }
218 280
219 public byte[] GetMapTile(string fileName, out string format) 281 public byte[] GetMapTile(string fileName, UUID scopeID, out string format)
220 { 282 {
221 format = string.Empty; 283 format = string.Empty;
222 new Exception("GetMapTile method not Implemented"); 284 new Exception("GetMapTile method not Implemented");
diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
index 925364a..939059d 100644
--- a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
@@ -153,9 +153,9 @@ namespace OpenSim.Services.Connectors
153 } 153 }
154 catch (Exception e) 154 catch (Exception e)
155 { 155 {
156 m_log.Warn(string.Format( 156// m_log.WarnFormat(
157 "[NEIGHBOUR SERVICES CONNECTOR]: Unable to send HelloNeighbour from {0} to {1} (uri {2}). Exception {3} ", 157// "[NEIGHBOUR SERVICE CONNCTOR]: Unable to send HelloNeighbour from {0} to {1}. Exception {2}{3}",
158 thisRegion.RegionName, region.RegionName, uri, e.Message), e); 158// thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
159 159
160 return false; 160 return false;
161 } 161 }
diff --git a/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs
index b7e95c4..1f14b32 100644
--- a/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs
@@ -313,6 +313,17 @@ namespace OpenSim.Services.Connectors
313 { 313 {
314 pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]); 314 pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]);
315 } 315 }
316 else
317 {
318 if (replyData["result"].ToString() == "null")
319 return null;
320
321 m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply (result not dictionary) received from presence server when querying for sessionID {0}", sessionID.ToString());
322 }
323 }
324 else
325 {
326 m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply received from presence server when querying for sessionID {0}", sessionID.ToString());
316 } 327 }
317 328
318 return pinfo; 329 return pinfo;
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
index 3bd11d9..c402907 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
@@ -102,6 +102,12 @@ namespace OpenSim.Services.Connectors.SimianGrid
102 m_log.Info("[SIMIAN AUTH CONNECTOR]: No AuthenticationServerURI specified, disabling connector"); 102 m_log.Info("[SIMIAN AUTH CONNECTOR]: No AuthenticationServerURI specified, disabling connector");
103 } 103 }
104 104
105 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
106 {
107 realID = UUID.Zero;
108 return Authenticate(principalID, password, lifetime);
109 }
110
105 public string Authenticate(UUID principalID, string password, int lifetime) 111 public string Authenticate(UUID principalID, string password, int lifetime)
106 { 112 {
107 NameValueCollection requestArgs = new NameValueCollection 113 NameValueCollection requestArgs = new NameValueCollection
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
index a397740..a52dd6c 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
@@ -152,7 +152,8 @@ namespace OpenSim.Services.Connectors.SimianGrid
152 // <param name=""></param> 152 // <param name=""></param>
153 public bool SetAppearance(UUID userID, AvatarAppearance appearance) 153 public bool SetAppearance(UUID userID, AvatarAppearance appearance)
154 { 154 {
155 OSDMap map = appearance.Pack(); 155 EntityTransferContext ctx = new EntityTransferContext();
156 OSDMap map = appearance.Pack(ctx);
156 if (map == null) 157 if (map == null)
157 { 158 {
158 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to encode appearance for {0}",userID); 159 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to encode appearance for {0}",userID);
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index b031f21..bd35c6f 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -28,6 +28,8 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Collections.Specialized; 30using System.Collections.Specialized;
31using System.Drawing;
32using System.Drawing.Imaging;
31using System.IO; 33using System.IO;
32using System.Net; 34using System.Net;
33using System.Reflection; 35using System.Reflection;
@@ -100,6 +102,15 @@ namespace OpenSim.Services.Connectors.SimianGrid
100 102
101 public string RegisterRegion(UUID scopeID, GridRegion regionInfo) 103 public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
102 { 104 {
105 IPEndPoint ext = regionInfo.ExternalEndPoint;
106 if (ext == null) return "Region registration for " + regionInfo.RegionName + " failed: Could not resolve EndPoint";
107 // Generate and upload our map tile in PNG format to the SimianGrid AddMapTile service
108// Scene scene;
109// if (m_scenes.TryGetValue(regionInfo.RegionID, out scene))
110// UploadMapTile(scene);
111// else
112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
113
103 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); 114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
104 Vector3d maxPosition = minPosition + new Vector3d(regionInfo.RegionSizeX, regionInfo.RegionSizeY, Constants.RegionHeight); 115 Vector3d maxPosition = minPosition + new Vector3d(regionInfo.RegionSizeX, regionInfo.RegionSizeY, Constants.RegionHeight);
105 116
@@ -108,7 +119,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
108 { "ServerURI", OSD.FromString(regionInfo.ServerURI) }, 119 { "ServerURI", OSD.FromString(regionInfo.ServerURI) },
109 { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) }, 120 { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) },
110 { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) }, 121 { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) },
111 { "ExternalAddress", OSD.FromString(regionInfo.ExternalEndPoint.Address.ToString()) }, 122 { "ExternalAddress", OSD.FromString(ext.Address.ToString()) },
112 { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) }, 123 { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) },
113 { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) }, 124 { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) },
114 { "Access", OSD.FromInteger(regionInfo.Access) }, 125 { "Access", OSD.FromInteger(regionInfo.Access) },
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
index 698c4c0..563a1e7 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
@@ -196,6 +196,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
196 m_accountCache.Remove(userID); 196 m_accountCache.Remove(userID);
197 } 197 }
198 198
199 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
200 {
201 return null;
202 }
203
199 public bool StoreUserAccount(UserAccount data) 204 public bool StoreUserAccount(UserAccount data)
200 { 205 {
201// m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name); 206// m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name);
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index cea870b..5dc4897 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -98,13 +98,13 @@ namespace OpenSim.Services.Connectors.Simulation
98 args["teleport_flags"] = OSD.FromString(flags.ToString()); 98 args["teleport_flags"] = OSD.FromString(flags.ToString());
99 } 99 }
100 100
101 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) 101 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, EntityTransferContext ctx, out string reason)
102 { 102 {
103 string tmp = String.Empty; 103 string tmp = String.Empty;
104 return CreateAgent(source, destination, aCircuit, flags, out tmp, out reason); 104 return CreateAgent(source, destination, aCircuit, flags, ctx, out tmp, out reason);
105 } 105 }
106 106
107 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason) 107 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, EntityTransferContext ctx, out string myipaddress, out string reason)
108 { 108 {
109 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI); 109 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI);
110 reason = String.Empty; 110 reason = String.Empty;
@@ -112,6 +112,7 @@ namespace OpenSim.Services.Connectors.Simulation
112 112
113 if (destination == null) 113 if (destination == null)
114 { 114 {
115 reason = "Destination not found";
115 m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null"); 116 m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null");
116 return false; 117 return false;
117 } 118 }
@@ -120,7 +121,8 @@ namespace OpenSim.Services.Connectors.Simulation
120 121
121 try 122 try
122 { 123 {
123 OSDMap args = aCircuit.PackAgentCircuitData(); 124 OSDMap args = aCircuit.PackAgentCircuitData(ctx);
125 args["context"] = ctx.Pack();
124 PackData(args, source, aCircuit, destination, flags); 126 PackData(args, source, aCircuit, destination, flags);
125 127
126 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); 128 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
@@ -171,9 +173,9 @@ namespace OpenSim.Services.Connectors.Simulation
171 /// <summary> 173 /// <summary>
172 /// Send complete data about an agent in this region to a neighbor 174 /// Send complete data about an agent in this region to a neighbor
173 /// </summary> 175 /// </summary>
174 public bool UpdateAgent(GridRegion destination, AgentData data) 176 public bool UpdateAgent(GridRegion destination, AgentData data, EntityTransferContext ctx)
175 { 177 {
176 return UpdateAgent(destination, (IAgentData)data, 200000); // yes, 200 seconds 178 return UpdateAgent(destination, (IAgentData)data, ctx, 200000); // yes, 200 seconds
177 } 179 }
178 180
179 private ExpiringCache<string, bool> _failedSims = new ExpiringCache<string, bool>(); 181 private ExpiringCache<string, bool> _failedSims = new ExpiringCache<string, bool>();
@@ -234,7 +236,8 @@ namespace OpenSim.Services.Connectors.Simulation
234 } 236 }
235 } 237 }
236 238
237 success = UpdateAgent(destination, (IAgentData)pos, 10000); 239 EntityTransferContext ctx = new EntityTransferContext(); // Dummy, not needed for position
240 success = UpdateAgent(destination, (IAgentData)pos, ctx, 10000);
238 } 241 }
239 // we get here iff success == false 242 // we get here iff success == false
240 // blacklist sim for 2 minutes 243 // blacklist sim for 2 minutes
@@ -249,7 +252,7 @@ namespace OpenSim.Services.Connectors.Simulation
249 /// <summary> 252 /// <summary>
250 /// This is the worker function to send AgentData to a neighbor region 253 /// This is the worker function to send AgentData to a neighbor region
251 /// </summary> 254 /// </summary>
252 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout) 255 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, EntityTransferContext ctx, int timeout)
253 { 256 {
254 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI); 257 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI);
255 258
@@ -258,12 +261,13 @@ namespace OpenSim.Services.Connectors.Simulation
258 261
259 try 262 try
260 { 263 {
261 OSDMap args = cAgentData.Pack(); 264 OSDMap args = cAgentData.Pack(ctx);
262 265
263 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); 266 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
264 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); 267 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
265 args["destination_name"] = OSD.FromString(destination.RegionName); 268 args["destination_name"] = OSD.FromString(destination.RegionName);
266 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); 269 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
270 args["context"] = ctx.Pack();
267 271
268 OSDMap result = WebUtil.PutToServiceCompressed(uri, args, timeout); 272 OSDMap result = WebUtil.PutToServiceCompressed(uri, args, timeout);
269 if (result["Success"].AsBoolean()) 273 if (result["Success"].AsBoolean())
@@ -306,6 +310,8 @@ namespace OpenSim.Services.Connectors.Simulation
306 request.Add("simulation_service_accepted_min", OSD.FromReal(VersionInfo.SimulationServiceVersionAcceptedMin)); 310 request.Add("simulation_service_accepted_min", OSD.FromReal(VersionInfo.SimulationServiceVersionAcceptedMin));
307 request.Add("simulation_service_accepted_max", OSD.FromReal(VersionInfo.SimulationServiceVersionAcceptedMax)); 311 request.Add("simulation_service_accepted_max", OSD.FromReal(VersionInfo.SimulationServiceVersionAcceptedMax));
308 312
313 request.Add("context", ctx.Pack());
314
309 OSDArray features = new OSDArray(); 315 OSDArray features = new OSDArray();
310 foreach (UUID feature in featuresAvailable) 316 foreach (UUID feature in featuresAvailable)
311 features.Add(OSD.FromString(feature.ToString())); 317 features.Add(OSD.FromString(feature.ToString()));
@@ -345,8 +351,6 @@ namespace OpenSim.Services.Connectors.Simulation
345 ctx.OutboundVersion = float.Parse(parts[1]); 351 ctx.OutboundVersion = float.Parse(parts[1]);
346 } 352 }
347 } 353 }
348 if (data.ContainsKey("variable_wearables_count_supported"))
349 ctx.VariableWearablesSupported = true;
350 354
351 m_log.DebugFormat( 355 m_log.DebugFormat(
352 "[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}, reason {2}, version {3}/{4}", 356 "[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}, reason {2}, version {3}/{4}",
@@ -379,7 +383,6 @@ namespace OpenSim.Services.Connectors.Simulation
379 return false; 383 return false;
380 } 384 }
381 385
382
383 featuresAvailable.Clear(); 386 featuresAvailable.Clear();
384 387
385 if (result.ContainsKey("features")) 388 if (result.ContainsKey("features"))
@@ -390,6 +393,10 @@ namespace OpenSim.Services.Connectors.Simulation
390 featuresAvailable.Add(new UUID(o.AsString())); 393 featuresAvailable.Add(new UUID(o.AsString()));
391 } 394 }
392 395
396 // Version stuff
397 if (ctx.OutboundVersion < 0.4)
398 ctx.WearablesCount = AvatarWearable.LEGACY_VERSION_MAX_WEARABLES;
399
393 return success; 400 return success;
394 } 401 }
395 catch (Exception e) 402 catch (Exception e)
diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs
index c21db54..3de0a20 100644
--- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs
+++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs
@@ -195,6 +195,11 @@ namespace OpenSim.Services.Connectors
195 { 195 {
196 } 196 }
197 197
198 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where)
199 {
200 return null; // Not implemented for regions
201 }
202
198 public virtual bool StoreUserAccount(UserAccount data) 203 public virtual bool StoreUserAccount(UserAccount data)
199 { 204 {
200 Dictionary<string, object> sendData = new Dictionary<string, object>(); 205 Dictionary<string, object> sendData = new Dictionary<string, object>();
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index 8807397..53805d0 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Services.GridService
57 protected bool m_AllowDuplicateNames = false; 57 protected bool m_AllowDuplicateNames = false;
58 protected bool m_AllowHypergridMapSearch = false; 58 protected bool m_AllowHypergridMapSearch = false;
59 59
60
60 protected bool m_SuppressVarregionOverlapCheckOnRegistration = false; 61 protected bool m_SuppressVarregionOverlapCheckOnRegistration = false;
61 62
62 private static Dictionary<string,object> m_ExtraFeatures = new Dictionary<string, object>(); 63 private static Dictionary<string,object> m_ExtraFeatures = new Dictionary<string, object>();
@@ -155,9 +156,9 @@ namespace OpenSim.Services.GridService
155 156
156 if (loginConfig == null || gridConfig == null) 157 if (loginConfig == null || gridConfig == null)
157 return; 158 return;
158 159
159 string configVal; 160 string configVal;
160 161
161 configVal = loginConfig.GetString("SearchURL", string.Empty); 162 configVal = loginConfig.GetString("SearchURL", string.Empty);
162 if (!string.IsNullOrEmpty(configVal)) 163 if (!string.IsNullOrEmpty(configVal))
163 m_ExtraFeatures["search-server-url"] = configVal; 164 m_ExtraFeatures["search-server-url"] = configVal;
@@ -202,14 +203,10 @@ namespace OpenSim.Services.GridService
202 return "Invalid RegionID - cannot be zero UUID"; 203 return "Invalid RegionID - cannot be zero UUID";
203 204
204 String reason = "Region overlaps another region"; 205 String reason = "Region overlaps another region";
205 RegionData region = FindAnyConflictingRegion(regionInfos, scopeID, out reason); 206 // we should not need to check for overlaps
206 // If there is a conflicting region, if it has the same ID and same coordinates 207
207 // then it is a region re-registering (permissions and ownership checked later). 208 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
208 if ((region != null) 209 if ((region != null) && (region.RegionID != regionInfos.RegionID))
209 && ( (region.coordX != regionInfos.RegionCoordX)
210 || (region.coordY != regionInfos.RegionCoordY)
211 || (region.RegionID != regionInfos.RegionID) )
212 )
213 { 210 {
214 // If not same ID and same coordinates, this new region has conflicts and can't be registered. 211 // If not same ID and same coordinates, this new region has conflicts and can't be registered.
215 m_log.WarnFormat("{0} Register region conflict in scope {1}. {2}", LogHeader, scopeID, reason); 212 m_log.WarnFormat("{0} Register region conflict in scope {1}. {2}", LogHeader, scopeID, reason);
@@ -463,7 +460,7 @@ namespace OpenSim.Services.GridService
463 460
464 int flags = Convert.ToInt32(region.Data["flags"]); 461 int flags = Convert.ToInt32(region.Data["flags"]);
465 462
466 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Framework.RegionFlags.Persistent) != 0) 463 if ((!m_DeleteOnUnregister) || ((flags & (int)OpenSim.Framework.RegionFlags.Persistent) != 0))
467 { 464 {
468 flags &= ~(int)OpenSim.Framework.RegionFlags.RegionOnline; 465 flags &= ~(int)OpenSim.Framework.RegionFlags.RegionOnline;
469 region.Data["flags"] = flags.ToString(); 466 region.Data["flags"] = flags.ToString();
@@ -478,7 +475,6 @@ namespace OpenSim.Services.GridService
478 } 475 }
479 476
480 return true; 477 return true;
481
482 } 478 }
483 479
484 return m_Database.Delete(regionID); 480 return m_Database.Delete(regionID);
@@ -491,10 +487,8 @@ namespace OpenSim.Services.GridService
491 487
492 if (region != null) 488 if (region != null)
493 { 489 {
494 // Not really? Maybe?
495 // The adjacent regions are presumed to be the same size as the current region
496 List<RegionData> rdatas = m_Database.Get( 490 List<RegionData> rdatas = m_Database.Get(
497 region.posX - region.sizeX - 1, region.posY - region.sizeY - 1, 491 region.posX - 1, region.posY - 1,
498 region.posX + region.sizeX + 1, region.posY + region.sizeY + 1, scopeID); 492 region.posX + region.sizeX + 1, region.posY + region.sizeY + 1, scopeID);
499 493
500 foreach (RegionData rdata in rdatas) 494 foreach (RegionData rdata in rdatas)
@@ -537,6 +531,7 @@ namespace OpenSim.Services.GridService
537 // be the base coordinate of the region. 531 // be the base coordinate of the region.
538 // The snapping is technically unnecessary but is harmless because regions are always 532 // The snapping is technically unnecessary but is harmless because regions are always
539 // multiples of the legacy region size (256). 533 // multiples of the legacy region size (256).
534
540 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 535 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
541 { 536 {
542 uint regionX = Util.WorldToRegionLoc((uint)x); 537 uint regionX = Util.WorldToRegionLoc((uint)x);
@@ -872,7 +867,9 @@ namespace OpenSim.Services.GridService
872 return; 867 return;
873 } 868 }
874 869
870
875 RegionData region = m_Database.Get((int)Util.RegionToWorldLoc(x), (int)Util.RegionToWorldLoc(y), UUID.Zero); 871 RegionData region = m_Database.Get((int)Util.RegionToWorldLoc(x), (int)Util.RegionToWorldLoc(y), UUID.Zero);
872
876 if (region == null) 873 if (region == null)
877 { 874 {
878 MainConsole.Instance.OutputFormat("No region found at {0},{1}", x, y); 875 MainConsole.Instance.OutputFormat("No region found at {0},{1}", x, y);
@@ -889,7 +886,7 @@ namespace OpenSim.Services.GridService
889 ConsoleDisplayList dispList = new ConsoleDisplayList(); 886 ConsoleDisplayList dispList = new ConsoleDisplayList();
890 dispList.AddRow("Region Name", r.RegionName); 887 dispList.AddRow("Region Name", r.RegionName);
891 dispList.AddRow("Region ID", r.RegionID); 888 dispList.AddRow("Region ID", r.RegionID);
892 dispList.AddRow("Position", string.Format("{0},{1}", r.coordX, r.coordY)); 889 dispList.AddRow("Location", string.Format("{0},{1}", r.coordX, r.coordY));
893 dispList.AddRow("Size", string.Format("{0}x{1}", r.sizeX, r.sizeY)); 890 dispList.AddRow("Size", string.Format("{0}x{1}", r.sizeX, r.sizeY));
894 dispList.AddRow("URI", r.Data["serverURI"]); 891 dispList.AddRow("URI", r.Data["serverURI"]);
895 dispList.AddRow("Owner ID", r.Data["owner_uuid"]); 892 dispList.AddRow("Owner ID", r.Data["owner_uuid"]);
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 9d016fc..2af617a 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -231,8 +231,7 @@ namespace OpenSim.Services.GridService
231 { 231 {
232 regionName = parts[2]; 232 regionName = parts[2];
233 } 233 }
234 234
235
236 bool success = TryCreateLink(scopeID, xloc, yloc, regionName, port, host, ownerID, out regInfo, out reason); 235 bool success = TryCreateLink(scopeID, xloc, yloc, regionName, port, host, ownerID, out regInfo, out reason);
237 if (success) 236 if (success)
238 { 237 {
@@ -379,8 +378,7 @@ namespace OpenSim.Services.GridService
379 region = m_GridService.GetRegionByUUID(scopeID, regionID); 378 region = m_GridService.GetRegionByUUID(scopeID, regionID);
380 if (region != null) 379 if (region != null)
381 { 380 {
382 m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates <{0},{1}>", 381 m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates <{0},{1}>", Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
383 Util.WorldToRegionLoc((uint)region.RegionLocX), Util.WorldToRegionLoc((uint)region.RegionLocY));
384 regInfo = region; 382 regInfo = region;
385 return true; 383 return true;
386 } 384 }
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
index 8e10125..9643a8b 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -459,7 +459,7 @@ namespace OpenSim.Services.HypergridService
459 true, aCircuit.startpos, new List<UUID>(), ctx, out reason)) 459 true, aCircuit.startpos, new List<UUID>(), ctx, out reason))
460 return false; 460 return false;
461 461
462 return m_SimulationService.CreateAgent(source, destination, aCircuit, (uint)loginFlag, out reason); 462 return m_SimulationService.CreateAgent(source, destination, aCircuit, (uint)loginFlag, ctx, out reason);
463 } 463 }
464 464
465 protected bool Authenticate(AgentCircuitData aCircuit) 465 protected bool Authenticate(AgentCircuitData aCircuit)
diff --git a/OpenSim/Services/HypergridService/UserAccountCache.cs b/OpenSim/Services/HypergridService/UserAccountCache.cs
index fa7dd0b..6c3c655 100644
--- a/OpenSim/Services/HypergridService/UserAccountCache.cs
+++ b/OpenSim/Services/HypergridService/UserAccountCache.cs
@@ -90,6 +90,11 @@ namespace OpenSim.Services.HypergridService
90 return null; 90 return null;
91 } 91 }
92 92
93 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
94 {
95 return null;
96 }
97
93 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 98 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
94 { 99 {
95 return null; 100 return null;
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index c65122a..317d006 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -281,7 +281,9 @@ namespace OpenSim.Services.HypergridService
281 } 281 }
282 else 282 else
283 { 283 {
284 success = m_GatekeeperConnector.CreateAgent(source, region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason); 284 //TODO: Should there not be a call to QueryAccess here?
285 EntityTransferContext ctx = new EntityTransferContext();
286 success = m_GatekeeperConnector.CreateAgent(source, region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, ctx, out myExternalIP, out reason);
285 } 287 }
286 288
287 if (!success) 289 if (!success)
diff --git a/OpenSim/Services/Interfaces/IAttachmentsService.cs b/OpenSim/Services/Interfaces/IAttachmentsService.cs
new file mode 100644
index 0000000..7d33662
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IAttachmentsService.cs
@@ -0,0 +1,38 @@
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;
30
31namespace OpenSim.Services.Interfaces
32{
33 public interface IAttachmentsService
34 {
35 string Get(string id);
36 void Store(string id, string data);
37 }
38}
diff --git a/OpenSim/Services/Interfaces/IAuthenticationService.cs b/OpenSim/Services/Interfaces/IAuthenticationService.cs
index cee8bc0..cdcfad9 100644
--- a/OpenSim/Services/Interfaces/IAuthenticationService.cs
+++ b/OpenSim/Services/Interfaces/IAuthenticationService.cs
@@ -67,6 +67,7 @@ namespace OpenSim.Services.Interfaces
67 // various services. 67 // various services.
68 // 68 //
69 string Authenticate(UUID principalID, string password, int lifetime); 69 string Authenticate(UUID principalID, string password, int lifetime);
70 string Authenticate(UUID principalID, string password, int lifetime, out UUID realID);
70 71
71 ////////////////////////////////////////////////////// 72 //////////////////////////////////////////////////////
72 // Verification 73 // Verification
diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs
index 892e0b4..99b71b9 100644
--- a/OpenSim/Services/Interfaces/IAvatarService.cs
+++ b/OpenSim/Services/Interfaces/IAvatarService.cs
@@ -150,7 +150,8 @@ namespace OpenSim.Services.Interfaces
150 // Wearables 150 // Wearables
151 Data["AvatarHeight"] = appearance.AvatarHeight.ToString(); 151 Data["AvatarHeight"] = appearance.AvatarHeight.ToString();
152 152
153 for (int i = 0 ; i < AvatarWearable.MAX_WEARABLES ; i++) 153 // TODO: With COF, is this even needed?
154 for (int i = 0 ; i < AvatarWearable.LEGACY_VERSION_MAX_WEARABLES ; i++)
154 { 155 {
155 for (int j = 0 ; j < appearance.Wearables[i].Count ; j++) 156 for (int j = 0 ; j < appearance.Wearables[i].Count ; j++)
156 { 157 {
@@ -211,8 +212,8 @@ namespace OpenSim.Services.Interfaces
211 float h = float.Parse(Data["AvatarHeight"]); 212 float h = float.Parse(Data["AvatarHeight"]);
212 if( h == 0f) 213 if( h == 0f)
213 h = 1.9f; 214 h = 1.9f;
214 215 appearance.SetSize(new Vector3(0.45f, 0.6f, h ));
215 appearance.AvatarHeight = h; 216// appearance.AvatarHeight = float.Parse(Data["AvatarHeight"]);
216 } 217 }
217 218
218 // Legacy Wearables 219 // Legacy Wearables
@@ -287,11 +288,10 @@ namespace OpenSim.Services.Interfaces
287 //byte[] binary = new byte[AvatarAppearance.VISUALPARAM_COUNT]; 288 //byte[] binary = new byte[AvatarAppearance.VISUALPARAM_COUNT];
288 289
289 //for (int i = 0 ; i < vps.Length && i < binary.Length ; i++) 290 //for (int i = 0 ; i < vps.Length && i < binary.Length ; i++)
290
291 byte[] binary = new byte[vps.Length]; 291 byte[] binary = new byte[vps.Length];
292 292
293 for (int i = 0; i < vps.Length; i++) 293 for (int i = 0; i < vps.Length; i++)
294 binary[i] = (byte)Convert.ToInt32(vps[i]); 294 binary[i] = (byte)Convert.ToInt32(vps[i]);
295 295
296 appearance.VisualParams = binary; 296 appearance.VisualParams = binary;
297 } 297 }
@@ -357,6 +357,7 @@ namespace OpenSim.Services.Interfaces
357 appearance.Wearables[AvatarWearable.EYES].Wear( 357 appearance.Wearables[AvatarWearable.EYES].Wear(
358 AvatarWearable.DefaultWearables[ 358 AvatarWearable.DefaultWearables[
359 AvatarWearable.EYES][0]); 359 AvatarWearable.EYES][0]);
360
360 } 361 }
361 catch 362 catch
362 { 363 {
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index f5f1f75..63c6e5f 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -159,13 +159,24 @@ namespace OpenSim.Services.Interfaces
159 } 159 }
160 } 160 }
161 set { 161 set {
162 if (value.EndsWith("/")) { 162 if ( value == null)
163 {
164 m_serverURI = String.Empty;
165 return;
166 }
167
168 if ( value.EndsWith("/") )
169 {
170
163 m_serverURI = value; 171 m_serverURI = value;
164 } else { 172 }
173 else
174 {
165 m_serverURI = value + '/'; 175 m_serverURI = value + '/';
166 } 176 }
167 } 177 }
168 } 178 }
179
169 protected string m_serverURI; 180 protected string m_serverURI;
170 181
171 /// <summary> 182 /// <summary>
@@ -358,6 +369,13 @@ namespace OpenSim.Services.Interfaces
358 if (kvp.ContainsKey("regionName")) 369 if (kvp.ContainsKey("regionName"))
359 RegionName = (string)kvp["regionName"]; 370 RegionName = (string)kvp["regionName"];
360 371
372 if (kvp.ContainsKey("access"))
373 {
374 byte access = Convert.ToByte((string)kvp["access"]);
375 Access = access;
376 Maturity = (int)Util.ConvertAccessLevelToMaturity(access);
377 }
378
361 if (kvp.ContainsKey("flags") && kvp["flags"] != null) 379 if (kvp.ContainsKey("flags") && kvp["flags"] != null)
362 RegionFlags = (OpenSim.Framework.RegionFlags?)Convert.ToInt32((string)kvp["flags"]); 380 RegionFlags = (OpenSim.Framework.RegionFlags?)Convert.ToInt32((string)kvp["flags"]);
363 381
@@ -394,9 +412,6 @@ namespace OpenSim.Services.Interfaces
394 if (kvp.ContainsKey("parcelMapTexture")) 412 if (kvp.ContainsKey("parcelMapTexture"))
395 UUID.TryParse((string)kvp["parcelMapTexture"], out ParcelImage); 413 UUID.TryParse((string)kvp["parcelMapTexture"], out ParcelImage);
396 414
397 if (kvp.ContainsKey("access"))
398 Access = Byte.Parse((string)kvp["access"]);
399
400 if (kvp.ContainsKey("regionSecret")) 415 if (kvp.ContainsKey("regionSecret"))
401 RegionSecret =(string)kvp["regionSecret"]; 416 RegionSecret =(string)kvp["regionSecret"];
402 417
@@ -500,9 +515,13 @@ namespace OpenSim.Services.Interfaces
500 } 515 }
501 catch (SocketException e) 516 catch (SocketException e)
502 { 517 {
503 throw new Exception( 518 /*throw new Exception(
504 "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" + 519 "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" +
505 e + "' attached to this exception", e); 520 e + "' attached to this exception", e);*/
521 // Don't throw a fatal exception here, instead, return Null and handle it in the caller.
522 // Reason is, on systems such as OSgrid it has occured that known hostnames stop
523 // resolving and thus make surrounding regions crash out with this exception.
524 return null;
506 } 525 }
507 526
508 return new IPEndPoint(ia, m_internalEndPoint.Port); 527 return new IPEndPoint(ia, m_internalEndPoint.Port);
@@ -526,4 +545,4 @@ namespace OpenSim.Services.Interfaces
526 get { return Util.UIntsToLong((uint)RegionLocX, (uint)RegionLocY); } 545 get { return Util.UIntsToLong((uint)RegionLocX, (uint)RegionLocY); }
527 } 546 }
528 } 547 }
529} \ No newline at end of file 548}
diff --git a/OpenSim/Services/Interfaces/ILoginService.cs b/OpenSim/Services/Interfaces/ILoginService.cs
index ee9b0b1..7c44cd8 100644
--- a/OpenSim/Services/Interfaces/ILoginService.cs
+++ b/OpenSim/Services/Interfaces/ILoginService.cs
@@ -47,8 +47,8 @@ namespace OpenSim.Services.Interfaces
47 47
48 public interface ILoginService 48 public interface ILoginService
49 { 49 {
50 LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, 50 LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID,
51 string clientVersion, string channel, string mac, string id0, IPEndPoint clientIP); 51 string clientVersion, string channel, string mac, string id0, IPEndPoint clientIP, bool LibOMVclient);
52 Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP); 52 Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP);
53 } 53 }
54 54
diff --git a/OpenSim/Services/Interfaces/IMapImageService.cs b/OpenSim/Services/Interfaces/IMapImageService.cs
index 78daa5f..b8d45dd 100644
--- a/OpenSim/Services/Interfaces/IMapImageService.cs
+++ b/OpenSim/Services/Interfaces/IMapImageService.cs
@@ -34,8 +34,8 @@ namespace OpenSim.Services.Interfaces
34 public interface IMapImageService 34 public interface IMapImageService
35 { 35 {
36 //List<MapBlockData> GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); 36 //List<MapBlockData> GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY);
37 bool AddMapTile(int x, int y, byte[] imageData, out string reason); 37 bool AddMapTile(int x, int y, byte[] imageData, UUID scopeID, out string reason);
38 bool RemoveMapTile(int x, int y, out string reason); 38 bool RemoveMapTile(int x, int y, UUID scopeID, out string reason);
39 byte[] GetMapTile(string fileName, out string format); 39 byte[] GetMapTile(string fileName, UUID scopeID, out string format);
40 } 40 }
41} 41}
diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs
index 8a25509..d89f6ff 100644
--- a/OpenSim/Services/Interfaces/ISimulationService.cs
+++ b/OpenSim/Services/Interfaces/ISimulationService.cs
@@ -34,20 +34,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
34 34
35namespace OpenSim.Services.Interfaces 35namespace OpenSim.Services.Interfaces
36{ 36{
37 public class EntityTransferContext
38 {
39 public EntityTransferContext()
40 {
41 InboundVersion = VersionInfo.SimulationServiceVersionAcceptedMax;
42 OutboundVersion = VersionInfo.SimulationServiceVersionSupportedMax;
43 VariableWearablesSupported = false;
44 }
45
46 public float InboundVersion { get; set; }
47 public float OutboundVersion { get; set; }
48 public bool VariableWearablesSupported { get; set; }
49 }
50
51 public interface ISimulationService 37 public interface ISimulationService
52 { 38 {
53 /// <summary> 39 /// <summary>
@@ -74,7 +60,7 @@ namespace OpenSim.Services.Interfaces
74 /// <param name="aCircuit"></param> 60 /// <param name="aCircuit"></param>
75 /// <param name="flags"></param> 61 /// <param name="flags"></param>
76 /// <param name="reason">Reason message in the event of a failure.</param> 62 /// <param name="reason">Reason message in the event of a failure.</param>
77 bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason); 63 bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, EntityTransferContext ctx, out string reason);
78 64
79 /// <summary> 65 /// <summary>
80 /// Full child agent update. 66 /// Full child agent update.
@@ -82,7 +68,7 @@ namespace OpenSim.Services.Interfaces
82 /// <param name="regionHandle"></param> 68 /// <param name="regionHandle"></param>
83 /// <param name="data"></param> 69 /// <param name="data"></param>
84 /// <returns></returns> 70 /// <returns></returns>
85 bool UpdateAgent(GridRegion destination, AgentData data); 71 bool UpdateAgent(GridRegion destination, AgentData data, EntityTransferContext ctx);
86 72
87 /// <summary> 73 /// <summary>
88 /// Short child agent update, mostly for position. 74 /// Short child agent update, mostly for position.
@@ -100,6 +86,7 @@ namespace OpenSim.Services.Interfaces
100 /// <param name="agentHomeURI">The visitor's Home URI. Will be missing (null) in older OpenSims.</param> 86 /// <param name="agentHomeURI">The visitor's Home URI. Will be missing (null) in older OpenSims.</param>
101 /// <param name="viaTeleport">True: via teleport; False: via cross (walking)</param> 87 /// <param name="viaTeleport">True: via teleport; False: via cross (walking)</param>
102 /// <param name="position">Position in the region</param> 88 /// <param name="position">Position in the region</param>
89
103 /// <param name="sversion"> 90 /// <param name="sversion">
104 /// Version that the requesting simulator is runing. If null then no version check is carried out. 91 /// Version that the requesting simulator is runing. If null then no version check is carried out.
105 /// </param> 92 /// </param>
diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs
index 2f7702c..1814699 100644
--- a/OpenSim/Services/Interfaces/IUserAccountService.cs
+++ b/OpenSim/Services/Interfaces/IUserAccountService.cs
@@ -91,6 +91,7 @@ namespace OpenSim.Services.Interfaces
91 public int UserLevel; 91 public int UserLevel;
92 public int UserFlags; 92 public int UserFlags;
93 public string UserTitle; 93 public string UserTitle;
94 public string UserCountry;
94 public Boolean LocalToGrid = true; 95 public Boolean LocalToGrid = true;
95 96
96 public Dictionary<string, object> ServiceURLs; 97 public Dictionary<string, object> ServiceURLs;
@@ -120,6 +121,8 @@ namespace OpenSim.Services.Interfaces
120 UserFlags = Convert.ToInt32(kvp["UserFlags"].ToString()); 121 UserFlags = Convert.ToInt32(kvp["UserFlags"].ToString());
121 if (kvp.ContainsKey("UserTitle")) 122 if (kvp.ContainsKey("UserTitle"))
122 UserTitle = kvp["UserTitle"].ToString(); 123 UserTitle = kvp["UserTitle"].ToString();
124 if (kvp.ContainsKey("UserCountry"))
125 UserCountry = kvp["UserCountry"].ToString();
123 if (kvp.ContainsKey("LocalToGrid")) 126 if (kvp.ContainsKey("LocalToGrid"))
124 Boolean.TryParse(kvp["LocalToGrid"].ToString(), out LocalToGrid); 127 Boolean.TryParse(kvp["LocalToGrid"].ToString(), out LocalToGrid);
125 128
@@ -155,6 +158,7 @@ namespace OpenSim.Services.Interfaces
155 result["UserLevel"] = UserLevel.ToString(); 158 result["UserLevel"] = UserLevel.ToString();
156 result["UserFlags"] = UserFlags.ToString(); 159 result["UserFlags"] = UserFlags.ToString();
157 result["UserTitle"] = UserTitle; 160 result["UserTitle"] = UserTitle;
161 result["UserCountry"] = UserCountry;
158 result["LocalToGrid"] = LocalToGrid.ToString(); 162 result["LocalToGrid"] = LocalToGrid.ToString();
159 163
160 string str = string.Empty; 164 string str = string.Empty;
@@ -182,6 +186,7 @@ namespace OpenSim.Services.Interfaces
182 /// <param name="query"></param> 186 /// <param name="query"></param>
183 /// <returns></returns> 187 /// <returns></returns>
184 List<UserAccount> GetUserAccounts(UUID scopeID, string query); 188 List<UserAccount> GetUserAccounts(UUID scopeID, string query);
189 List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where);
185 190
186 /// <summary> 191 /// <summary>
187 /// Store the data given, wich replaces the stored data, therefore must be complete. 192 /// Store the data given, wich replaces the stored data, therefore must be complete.
diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
index c3756d0..0f57c2e 100644
--- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Services.LLLoginService
55 public static LLFailedLoginResponse InventoryProblem; 55 public static LLFailedLoginResponse InventoryProblem;
56 public static LLFailedLoginResponse DeadRegionProblem; 56 public static LLFailedLoginResponse DeadRegionProblem;
57 public static LLFailedLoginResponse LoginBlockedProblem; 57 public static LLFailedLoginResponse LoginBlockedProblem;
58 public static LLFailedLoginResponse UnverifiedAccountProblem;
58 public static LLFailedLoginResponse AlreadyLoggedInProblem; 59 public static LLFailedLoginResponse AlreadyLoggedInProblem;
59 public static LLFailedLoginResponse InternalError; 60 public static LLFailedLoginResponse InternalError;
60 61
@@ -75,6 +76,10 @@ namespace OpenSim.Services.LLLoginService
75 LoginBlockedProblem = new LLFailedLoginResponse("presence", 76 LoginBlockedProblem = new LLFailedLoginResponse("presence",
76 "Logins are currently restricted. Please try again later.", 77 "Logins are currently restricted. Please try again later.",
77 "false"); 78 "false");
79 UnverifiedAccountProblem = new LLFailedLoginResponse("presence",
80 "Your account has not yet been verified. Please check " +
81 "your email and click the provided link.",
82 "false");
78 AlreadyLoggedInProblem = new LLFailedLoginResponse("presence", 83 AlreadyLoggedInProblem = new LLFailedLoginResponse("presence",
79 "You appear to be already logged in. " + 84 "You appear to be already logged in. " +
80 "If this is not the case please wait for your session to timeout. " + 85 "If this is not the case please wait for your session to timeout. " +
@@ -145,6 +150,7 @@ namespace OpenSim.Services.LLLoginService
145 private UUID agentID; 150 private UUID agentID;
146 private UUID sessionID; 151 private UUID sessionID;
147 private UUID secureSessionID; 152 private UUID secureSessionID;
153 private UUID realID;
148 154
149 // Login Flags 155 // Login Flags
150 private string dst; 156 private string dst;
@@ -228,8 +234,9 @@ namespace OpenSim.Services.LLLoginService
228 public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, GridUserInfo pinfo, 234 public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, GridUserInfo pinfo,
229 GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService, 235 GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService,
230 string where, string startlocation, Vector3 position, Vector3 lookAt, List<InventoryItemBase> gestures, string message, 236 string where, string startlocation, Vector3 position, Vector3 lookAt, List<InventoryItemBase> gestures, string message,
231 GridRegion home, IPEndPoint clientIP, string mapTileURL, string searchURL, string currency, 237
232 string DSTZone, string destinationsURL, string avatarsURL, string classifiedFee, int maxAgentGroups) 238 GridRegion home, IPEndPoint clientIP, string mapTileURL, string profileURL, string openIDURL, string searchURL, string currency,
239 string DSTZone, string destinationsURL, string avatarsURL, UUID realID, string classifiedFee,int maxAgentGroups)
233 : this() 240 : this()
234 { 241 {
235 FillOutInventoryData(invSkel, libService); 242 FillOutInventoryData(invSkel, libService);
@@ -242,6 +249,7 @@ namespace OpenSim.Services.LLLoginService
242 AgentID = account.PrincipalID; 249 AgentID = account.PrincipalID;
243 SessionID = aCircuit.SessionID; 250 SessionID = aCircuit.SessionID;
244 SecureSessionID = aCircuit.SecureSessionID; 251 SecureSessionID = aCircuit.SecureSessionID;
252 RealID = realID;
245 Message = message; 253 Message = message;
246 BuddList = ConvertFriendListItem(friendsList); 254 BuddList = ConvertFriendListItem(friendsList);
247 StartLocation = where; 255 StartLocation = where;
@@ -383,6 +391,7 @@ namespace OpenSim.Services.LLLoginService
383 private void FillOutRegionData(GridRegion destination) 391 private void FillOutRegionData(GridRegion destination)
384 { 392 {
385 IPEndPoint endPoint = destination.ExternalEndPoint; 393 IPEndPoint endPoint = destination.ExternalEndPoint;
394 if (endPoint == null) return;
386 SimAddress = endPoint.Address.ToString(); 395 SimAddress = endPoint.Address.ToString();
387 SimPort = (uint)endPoint.Port; 396 SimPort = (uint)endPoint.Port;
388 RegionX = (uint)destination.RegionLocX; 397 RegionX = (uint)destination.RegionLocX;
@@ -473,6 +482,7 @@ namespace OpenSim.Services.LLLoginService
473 SessionID = UUID.Random(); 482 SessionID = UUID.Random();
474 SecureSessionID = UUID.Random(); 483 SecureSessionID = UUID.Random();
475 AgentID = UUID.Random(); 484 AgentID = UUID.Random();
485 RealID = UUID.Zero;
476 486
477 Hashtable InitialOutfitHash = new Hashtable(); 487 Hashtable InitialOutfitHash = new Hashtable();
478 InitialOutfitHash["folder_name"] = "Nightclub Female"; 488 InitialOutfitHash["folder_name"] = "Nightclub Female";
@@ -518,6 +528,7 @@ namespace OpenSim.Services.LLLoginService
518 responseData["http_port"] = (Int32)SimHttpPort; 528 responseData["http_port"] = (Int32)SimHttpPort;
519 529
520 responseData["agent_id"] = AgentID.ToString(); 530 responseData["agent_id"] = AgentID.ToString();
531 responseData["real_id"] = RealID.ToString();
521 responseData["session_id"] = SessionID.ToString(); 532 responseData["session_id"] = SessionID.ToString();
522 responseData["secure_session_id"] = SecureSessionID.ToString(); 533 responseData["secure_session_id"] = SecureSessionID.ToString();
523 responseData["circuit_code"] = CircuitCode; 534 responseData["circuit_code"] = CircuitCode;
@@ -613,6 +624,7 @@ namespace OpenSim.Services.LLLoginService
613 map["sim_ip"] = OSD.FromString(SimAddress); 624 map["sim_ip"] = OSD.FromString(SimAddress);
614 625
615 map["agent_id"] = OSD.FromUUID(AgentID); 626 map["agent_id"] = OSD.FromUUID(AgentID);
627 map["real_id"] = OSD.FromUUID(RealID);
616 map["session_id"] = OSD.FromUUID(SessionID); 628 map["session_id"] = OSD.FromUUID(SessionID);
617 map["secure_session_id"] = OSD.FromUUID(SecureSessionID); 629 map["secure_session_id"] = OSD.FromUUID(SecureSessionID);
618 map["circuit_code"] = OSD.FromInteger(CircuitCode); 630 map["circuit_code"] = OSD.FromInteger(CircuitCode);
@@ -924,6 +936,12 @@ namespace OpenSim.Services.LLLoginService
924 set { secureSessionID = value; } 936 set { secureSessionID = value; }
925 } 937 }
926 938
939 public UUID RealID
940 {
941 get { return realID; }
942 set { realID = value; }
943 }
944
927 public Int32 CircuitCode 945 public Int32 CircuitCode
928 { 946 {
929 get { return circuitCode; } 947 get { return circuitCode; }
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 0b38738..6681f1a 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -77,6 +77,8 @@ namespace OpenSim.Services.LLLoginService
77 protected string m_GatekeeperURL; 77 protected string m_GatekeeperURL;
78 protected bool m_AllowRemoteSetLoginLevel; 78 protected bool m_AllowRemoteSetLoginLevel;
79 protected string m_MapTileURL; 79 protected string m_MapTileURL;
80 protected string m_ProfileURL;
81 protected string m_OpenIDURL;
80 protected string m_SearchURL; 82 protected string m_SearchURL;
81 protected string m_Currency; 83 protected string m_Currency;
82 protected string m_ClassifiedFee; 84 protected string m_ClassifiedFee;
@@ -117,6 +119,8 @@ namespace OpenSim.Services.LLLoginService
117 m_GatekeeperURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI", 119 m_GatekeeperURL = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI",
118 new string[] { "Startup", "Hypergrid", "LoginService" }, String.Empty); 120 new string[] { "Startup", "Hypergrid", "LoginService" }, String.Empty);
119 m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); 121 m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty);
122 m_ProfileURL = m_LoginServerConfig.GetString("ProfileServerURL", string.Empty);
123 m_OpenIDURL = m_LoginServerConfig.GetString("OpenIDServerURL", String.Empty);
120 m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); 124 m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty);
121 m_Currency = m_LoginServerConfig.GetString("Currency", string.Empty); 125 m_Currency = m_LoginServerConfig.GetString("Currency", string.Empty);
122 m_ClassifiedFee = m_LoginServerConfig.GetString("ClassifiedFee", string.Empty); 126 m_ClassifiedFee = m_LoginServerConfig.GetString("ClassifiedFee", string.Empty);
@@ -155,7 +159,8 @@ namespace OpenSim.Services.LLLoginService
155 Object[] args = new Object[] { config }; 159 Object[] args = new Object[] { config };
156 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); 160 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
157 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); 161 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
158 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args); 162 Object[] authArgs = new Object[] { config, m_UserAccountService };
163 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, authArgs);
159 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args); 164 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args);
160 165
161 if (gridService != string.Empty) 166 if (gridService != string.Empty)
@@ -261,14 +266,18 @@ namespace OpenSim.Services.LLLoginService
261 } 266 }
262 267
263 public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, 268 public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID,
264 string clientVersion, string channel, string mac, string id0, IPEndPoint clientIP) 269 string clientVersion, string channel, string mac, string id0, IPEndPoint clientIP, bool LibOMVclient)
265 { 270 {
266 bool success = false; 271 bool success = false;
267 UUID session = UUID.Random(); 272 UUID session = UUID.Random();
273
268 string processedMessage; 274 string processedMessage;
269 275
270 m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}", 276 if (clientVersion.Contains("Radegast"))
271 firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0); 277 LibOMVclient = false;
278
279 m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}, Possible LibOMVGridProxy: {8} ",
280 firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0, LibOMVclient.ToString());
272 281
273 try 282 try
274 { 283 {
@@ -345,7 +354,8 @@ namespace OpenSim.Services.LLLoginService
345 if (!passwd.StartsWith("$1$")) 354 if (!passwd.StartsWith("$1$"))
346 passwd = "$1$" + Util.Md5Hash(passwd); 355 passwd = "$1$" + Util.Md5Hash(passwd);
347 passwd = passwd.Remove(0, 3); //remove $1$ 356 passwd = passwd.Remove(0, 3); //remove $1$
348 string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30); 357 UUID realID;
358 string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30, out realID);
349 UUID secureSession = UUID.Zero; 359 UUID secureSession = UUID.Zero;
350 if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession))) 360 if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession)))
351 { 361 {
@@ -512,11 +522,11 @@ namespace OpenSim.Services.LLLoginService
512 processedMessage = processedMessage.Replace("\\n", "\n").Replace("<USERNAME>", firstName + " " + lastName); 522 processedMessage = processedMessage.Replace("\\n", "\n").Replace("<USERNAME>", firstName + " " + lastName);
513 523
514 LLLoginResponse response 524 LLLoginResponse response
515 = new LLLoginResponse( 525 = new LLLoginResponse(
516 account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService, 526 account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService,
517 where, startLocation, position, lookAt, gestures, processedMessage, home, clientIP, 527 where, startLocation, position, lookAt, gestures, processedMessage, home, clientIP,
518 m_MapTileURL, m_SearchURL, m_Currency, m_DSTZone, 528 m_MapTileURL, m_ProfileURL, m_OpenIDURL, m_SearchURL, m_Currency, m_DSTZone,
519 m_DestinationGuide, m_AvatarPicker, m_ClassifiedFee, m_MaxAgentGroups); 529 m_DestinationGuide, m_AvatarPicker, realID, m_ClassifiedFee,m_MaxAgentGroups);
520 530
521 m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName); 531 m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName);
522 532
@@ -989,7 +999,7 @@ namespace OpenSim.Services.LLLoginService
989 region, aCircuit.AgentID, null, true, aCircuit.startpos, new List<UUID>(), ctx, out reason)) 999 region, aCircuit.AgentID, null, true, aCircuit.startpos, new List<UUID>(), ctx, out reason))
990 return false; 1000 return false;
991 1001
992 return simConnector.CreateAgent(null, region, aCircuit, (uint)flags, out reason); 1002 return simConnector.CreateAgent(null, region, aCircuit, (uint)flags, ctx, out reason);
993 } 1003 }
994 1004
995 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) 1005 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason)
diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs
index a816411..6728752 100644
--- a/OpenSim/Services/MapImageService/MapImageService.cs
+++ b/OpenSim/Services/MapImageService/MapImageService.cs
@@ -69,6 +69,8 @@ namespace OpenSim.Services.MapImageService
69 private static bool m_Initialized = false; 69 private static bool m_Initialized = false;
70 private static string m_WaterTileFile = string.Empty; 70 private static string m_WaterTileFile = string.Empty;
71 private static Color m_Watercolor = Color.FromArgb(29, 71, 95); 71 private static Color m_Watercolor = Color.FromArgb(29, 71, 95);
72 private static Bitmap m_WaterBitmap = null;
73 private static byte[] m_WaterBytes = null;
72 74
73 public MapImageService(IConfigSource config) 75 public MapImageService(IConfigSource config)
74 { 76 {
@@ -91,6 +93,18 @@ namespace OpenSim.Services.MapImageService
91 Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); 93 Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH);
92 FillImage(waterTile, m_Watercolor); 94 FillImage(waterTile, m_Watercolor);
93 waterTile.Save(m_WaterTileFile, ImageFormat.Jpeg); 95 waterTile.Save(m_WaterTileFile, ImageFormat.Jpeg);
96 m_WaterBitmap = waterTile;
97 }
98
99 if (File.Exists(m_WaterTileFile))
100 {
101 m_WaterBitmap = new Bitmap(m_WaterTileFile);
102 using (MemoryStream ms = new MemoryStream())
103 {
104 m_WaterBitmap.Save(ms,ImageFormat.Jpeg);
105 ms.Seek(0, SeekOrigin.Begin);
106 m_WaterBytes = ms.ToArray();
107 }
94 } 108 }
95 } 109 }
96 } 110 }
@@ -98,10 +112,10 @@ namespace OpenSim.Services.MapImageService
98 112
99 #region IMapImageService 113 #region IMapImageService
100 114
101 public bool AddMapTile(int x, int y, byte[] imageData, out string reason) 115 public bool AddMapTile(int x, int y, byte[] imageData, UUID scopeID, out string reason)
102 { 116 {
103 reason = string.Empty; 117 reason = string.Empty;
104 string fileName = GetFileName(1, x, y); 118 string fileName = GetFileName(1, x, y, scopeID);
105 119
106 lock (m_Sync) 120 lock (m_Sync)
107 { 121 {
@@ -118,13 +132,13 @@ namespace OpenSim.Services.MapImageService
118 } 132 }
119 } 133 }
120 134
121 return UpdateMultiResolutionFilesAsync(x, y, out reason); 135 return UpdateMultiResolutionFiles(x, y, scopeID, out reason);
122 } 136 }
123 137
124 public bool RemoveMapTile(int x, int y, out string reason) 138 public bool RemoveMapTile(int x, int y, UUID scopeID, out string reason)
125 { 139 {
126 reason = String.Empty; 140 reason = String.Empty;
127 string fileName = GetFileName(1, x, y); 141 string fileName = GetFileName(1, x, y, scopeID);
128 142
129 lock (m_Sync) 143 lock (m_Sync)
130 { 144 {
@@ -134,15 +148,16 @@ namespace OpenSim.Services.MapImageService
134 } 148 }
135 catch (Exception e) 149 catch (Exception e)
136 { 150 {
151
137 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save delete file {0}: {1}", fileName, e); 152 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save delete file {0}: {1}", fileName, e);
138 reason = e.Message; 153 reason = e.Message;
139 return false; 154 return false;
140 } 155 }
141 } 156 }
142 157 return UpdateMultiResolutionFiles(x, y, scopeID, out reason);
143 return UpdateMultiResolutionFilesAsync(x, y, out reason);
144 } 158 }
145 159
160
146 // When large varregions start up, they can send piles of new map tiles. This causes 161 // When large varregions start up, they can send piles of new map tiles. This causes
147 // this multi-resolution routine to be called a zillion times an causes much CPU 162 // this multi-resolution routine to be called a zillion times an causes much CPU
148 // time to be spent creating multi-resolution tiles that will be replaced when 163 // time to be spent creating multi-resolution tiles that will be replaced when
@@ -151,23 +166,27 @@ namespace OpenSim.Services.MapImageService
151 { 166 {
152 public int xx; 167 public int xx;
153 public int yy; 168 public int yy;
154 public mapToMultiRez(int pX, int pY) 169 public UUID scopeID;
170 public mapToMultiRez(int pX, int pY, UUID pscopeID)
155 { 171 {
156 xx = pX; 172 xx = pX;
157 yy = pY; 173 yy = pY;
174 scopeID = pscopeID;
158 } 175 }
159 }; 176 };
160 private Queue<mapToMultiRez> multiRezToBuild = new Queue<mapToMultiRez>(); 177 private Queue<mapToMultiRez> multiRezToBuild = new Queue<mapToMultiRez>();
161 private bool UpdateMultiResolutionFilesAsync(int x, int y, out string reason) 178
179 private bool UpdateMultiResolutionFiles(int x, int y, UUID scopeID, out string reason)
162 { 180 {
163 reason = String.Empty; 181 reason = String.Empty;
182
164 lock (multiRezToBuild) 183 lock (multiRezToBuild)
165 { 184 {
166 // m_log.DebugFormat("{0} UpdateMultiResolutionFilesAsync: scheduling update for <{1},{2}>", LogHeader, x, y); 185 // m_log.DebugFormat("{0} UpdateMultiResolutionFilesAsync: scheduling update for <{1},{2}>", LogHeader, x, y);
167 multiRezToBuild.Enqueue(new mapToMultiRez(x, y)); 186 multiRezToBuild.Enqueue(new mapToMultiRez(x, y, scopeID));
168 if (multiRezToBuild.Count == 1) 187 if (multiRezToBuild.Count == 1)
169 Util.FireAndForget( 188 Util.FireAndForget(
170 DoUpdateMultiResolutionFilesAsync, null, "MapImageService.DoUpdateMultiResolutionFilesAsync"); 189 DoUpdateMultiResolutionFilesAsync);
171 } 190 }
172 191
173 return true; 192 return true;
@@ -175,10 +194,8 @@ namespace OpenSim.Services.MapImageService
175 194
176 private void DoUpdateMultiResolutionFilesAsync(object o) 195 private void DoUpdateMultiResolutionFilesAsync(object o)
177 { 196 {
178 // This sleep causes the FireAndForget thread to be different than the invocation thread. 197 // let acumulate large region tiles
179 // It also allows other tiles to be uploaded so the multi-rez images are more likely 198 Thread.Sleep(60 * 1000); // large regions take time to upload tiles
180 // to be correct.
181 Thread.Sleep(1 * 1000);
182 199
183 while (multiRezToBuild.Count > 0) 200 while (multiRezToBuild.Count > 0)
184 { 201 {
@@ -192,20 +209,23 @@ namespace OpenSim.Services.MapImageService
192 { 209 {
193 int x = toMultiRez.xx; 210 int x = toMultiRez.xx;
194 int y = toMultiRez.yy; 211 int y = toMultiRez.yy;
212 UUID scopeID = toMultiRez.scopeID;
195 // m_log.DebugFormat("{0} DoUpdateMultiResolutionFilesAsync: doing build for <{1},{2}>", LogHeader, x, y); 213 // m_log.DebugFormat("{0} DoUpdateMultiResolutionFilesAsync: doing build for <{1},{2}>", LogHeader, x, y);
196 214
215 int width = 1;
216
197 // Stitch seven more aggregate tiles together 217 // Stitch seven more aggregate tiles together
198 for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) 218 for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++)
199 { 219 {
200 // Calculate the width (in full resolution tiles) and bottom-left 220 // Calculate the width (in full resolution tiles) and bottom-left
201 // corner of the current zoom level 221 // corner of the current zoom level
202 int width = (int)Math.Pow(2, (double)(zoomLevel - 1)); 222 width *= 2;
203 int x1 = x - (x % width); 223 int x1 = x - (x % width);
204 int y1 = y - (y % width); 224 int y1 = y - (y % width);
205 225
206 lock (m_Sync) // must lock the reading and writing of the maptile files 226 lock (m_Sync) // must lock the reading and writing of the maptile files
207 { 227 {
208 if (!CreateTile(zoomLevel, x1, y1)) 228 if (!CreateTile(zoomLevel, x1, y1, scopeID))
209 { 229 {
210 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel); 230 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel);
211 return; 231 return;
@@ -214,25 +234,25 @@ namespace OpenSim.Services.MapImageService
214 } 234 }
215 } 235 }
216 } 236 }
217
218 return; 237 return;
219 } 238 }
220 239
221 public byte[] GetMapTile(string fileName, out string format) 240 public byte[] GetMapTile(string fileName, UUID scopeID, out string format)
222 { 241 {
223// m_log.DebugFormat("[MAP IMAGE SERVICE]: Getting map tile {0}", fileName); 242// m_log.DebugFormat("[MAP IMAGE SERVICE]: Getting map tile {0}", fileName);
224 243
225 format = ".jpg"; 244 format = ".jpg";
226 string fullName = Path.Combine(m_TilesStoragePath, fileName); 245 string fullName = Path.Combine(m_TilesStoragePath, scopeID.ToString());
246 fullName = Path.Combine(fullName, fileName);
227 if (File.Exists(fullName)) 247 if (File.Exists(fullName))
228 { 248 {
229 format = Path.GetExtension(fileName).ToLower(); 249 format = Path.GetExtension(fileName).ToLower();
230 //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); 250 //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format);
231 return File.ReadAllBytes(fullName); 251 return File.ReadAllBytes(fullName);
232 } 252 }
233 else if (File.Exists(m_WaterTileFile)) 253 else if (m_WaterBytes != null)
234 { 254 {
235 return File.ReadAllBytes(m_WaterTileFile); 255 return (byte[])m_WaterBytes.Clone();
236 } 256 }
237 else 257 else
238 { 258 {
@@ -244,10 +264,12 @@ namespace OpenSim.Services.MapImageService
244 #endregion 264 #endregion
245 265
246 266
247 private string GetFileName(uint zoomLevel, int x, int y) 267 private string GetFileName(uint zoomLevel, int x, int y, UUID scopeID)
248 { 268 {
249 string extension = "jpg"; 269 string extension = "jpg";
250 return Path.Combine(m_TilesStoragePath, string.Format("map-{0}-{1}-{2}-objects.{3}", zoomLevel, x, y, extension)); 270 string path = Path.Combine(m_TilesStoragePath, scopeID.ToString());
271 Directory.CreateDirectory(path);
272 return Path.Combine(path, string.Format("map-{0}-{1}-{2}-objects.{3}", zoomLevel, x, y, extension));
251 } 273 }
252 274
253 private Bitmap GetInputTileImage(string fileName) 275 private Bitmap GetInputTileImage(string fileName)
@@ -276,7 +298,7 @@ namespace OpenSim.Services.MapImageService
276 { 298 {
277 // Create a new output tile with a transparent background 299 // Create a new output tile with a transparent background
278 Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH, PixelFormat.Format24bppRgb); 300 Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH, PixelFormat.Format24bppRgb);
279 bm.MakeTransparent(); 301 //bm.MakeTransparent(); // 24bpp does not have transparency, this whould make it 32bpp
280 return bm; 302 return bm;
281 } 303 }
282 } 304 }
@@ -288,7 +310,7 @@ namespace OpenSim.Services.MapImageService
288 return null; 310 return null;
289 } 311 }
290 312
291 private bool CreateTile(uint zoomLevel, int x, int y) 313 private bool CreateTile(uint zoomLevel, int x, int y, UUID scopeID)
292 { 314 {
293// m_log.DebugFormat("[MAP IMAGE SERVICE]: Create tile for {0} {1}, zoom {2}", x, y, zoomLevel); 315// m_log.DebugFormat("[MAP IMAGE SERVICE]: Create tile for {0} {1}, zoom {2}", x, y, zoomLevel);
294 int prevWidth = (int)Math.Pow(2, (double)zoomLevel - 2); 316 int prevWidth = (int)Math.Pow(2, (double)zoomLevel - 2);
@@ -303,55 +325,60 @@ namespace OpenSim.Services.MapImageService
303 int yOut = y - (y % thisWidth); 325 int yOut = y - (y % thisWidth);
304 326
305 // Try to open the four input tiles from the previous zoom level 327 // Try to open the four input tiles from the previous zoom level
306 Bitmap inputBL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn)); 328 Bitmap inputBL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn, scopeID));
307 Bitmap inputBR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn)); 329 Bitmap inputBR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn, scopeID));
308 Bitmap inputTL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn + prevWidth)); 330 Bitmap inputTL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn + prevWidth, scopeID));
309 Bitmap inputTR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn + prevWidth)); 331 Bitmap inputTR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn + prevWidth, scopeID));
310 332
311 // Open the output tile (current zoom level) 333 // Open the output tile (current zoom level)
312 string outputFile = GetFileName(zoomLevel, xOut, yOut); 334 string outputFile = GetFileName(zoomLevel, xOut, yOut, scopeID);
313 Bitmap output = GetOutputTileImage(outputFile); 335
314 if (output == null) 336 int ntiles = 0;
315 return false; 337 Bitmap output = (Bitmap)m_WaterBitmap.Clone();
316 FillImage(output, m_Watercolor);
317 338
318 if (inputBL != null) 339 if (inputBL != null)
319 { 340 {
320 ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0); 341 ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0);
321 inputBL.Dispose(); 342 inputBL.Dispose();
343 ntiles++;
322 } 344 }
323 if (inputBR != null) 345 if (inputBR != null)
324 { 346 {
325 ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0); 347 ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0);
326 inputBR.Dispose(); 348 inputBR.Dispose();
349 ntiles++;
327 } 350 }
328 if (inputTL != null) 351 if (inputTL != null)
329 { 352 {
330 ImageCopyResampled(output, inputTL, 0, 0, 0, 0); 353 ImageCopyResampled(output, inputTL, 0, 0, 0, 0);
331 inputTL.Dispose(); 354 inputTL.Dispose();
355 ntiles++;
332 } 356 }
333 if (inputTR != null) 357 if (inputTR != null)
334 { 358 {
335 ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0); 359 ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0);
336 inputTR.Dispose(); 360 inputTR.Dispose();
361 ntiles++;
337 } 362 }
338 363
339 // Write the modified output 364 // Write the modified output
340 try 365 if (ntiles == 0)
366 File.Delete(outputFile);
367
368 else
341 { 369 {
342 using (Bitmap final = new Bitmap(output)) 370
371 try
343 { 372 {
344 output.Dispose(); 373 output.Save(outputFile, ImageFormat.Jpeg);
345 final.Save(outputFile, ImageFormat.Jpeg);
346 } 374 }
347 } 375 catch (Exception e)
348 catch (Exception e) 376 {
349 { 377 m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e);
350 m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e); 378 }
351 } 379 } // Save also as png?
352
353 // Save also as png?
354 380
381 output.Dispose();
355 return true; 382 return true;
356 } 383 }
357 384
diff --git a/OpenSim/Services/SimulationService/SimulationDataService.cs b/OpenSim/Services/SimulationService/SimulationDataService.cs
index d9684c4..7a544fa 100644
--- a/OpenSim/Services/SimulationService/SimulationDataService.cs
+++ b/OpenSim/Services/SimulationService/SimulationDataService.cs
@@ -173,6 +173,11 @@ namespace OpenSim.Services.SimulationService
173 m_database.RemoveRegionEnvironmentSettings(regionUUID); 173 m_database.RemoveRegionEnvironmentSettings(regionUUID);
174 } 174 }
175 175
176 public UUID[] GetObjectIDs(UUID regionID)
177 {
178 return m_database.GetObjectIDs(regionID);
179 }
180
176 public void SaveExtra(UUID regionID, string name, string val) 181 public void SaveExtra(UUID regionID, string name, string val)
177 { 182 {
178 m_database.SaveExtra(regionID, name, val); 183 m_database.SaveExtra(regionID, name, val);
diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs
index 2e19ece..987a07d 100644
--- a/OpenSim/Services/UserAccountService/UserAccountService.cs
+++ b/OpenSim/Services/UserAccountService/UserAccountService.cs
@@ -176,6 +176,10 @@ namespace OpenSim.Services.UserAccountService
176 Int32.TryParse(d.Data["UserLevel"], out u.UserLevel); 176 Int32.TryParse(d.Data["UserLevel"], out u.UserLevel);
177 if (d.Data.ContainsKey("UserFlags") && d.Data["UserFlags"] != null) 177 if (d.Data.ContainsKey("UserFlags") && d.Data["UserFlags"] != null)
178 Int32.TryParse(d.Data["UserFlags"], out u.UserFlags); 178 Int32.TryParse(d.Data["UserFlags"], out u.UserFlags);
179 if (d.Data.ContainsKey("UserCountry") && d.Data["UserCountry"] != null)
180 u.UserCountry = d.Data["UserCountry"].ToString();
181 else
182 u.UserTitle = string.Empty;
179 183
180 if (d.Data.ContainsKey("ServiceURLs") && d.Data["ServiceURLs"] != null) 184 if (d.Data.ContainsKey("ServiceURLs") && d.Data["ServiceURLs"] != null)
181 { 185 {
@@ -301,7 +305,22 @@ namespace OpenSim.Services.UserAccountService
301 305
302 public List<UserAccount> GetUserAccounts(UUID scopeID, string query) 306 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
303 { 307 {
304 UserAccountData[] d = m_Database.GetUsers(scopeID, query); 308 UserAccountData[] d = m_Database.GetUsers(scopeID, query.Trim());
309
310 if (d == null)
311 return new List<UserAccount>();
312
313 List<UserAccount> ret = new List<UserAccount>();
314
315 foreach (UserAccountData data in d)
316 ret.Add(MakeUserAccount(data));
317
318 return ret;
319 }
320
321 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where)
322 {
323 UserAccountData[] d = m_Database.GetUsersWhere(scopeID, where);
305 324
306 if (d == null) 325 if (d == null)
307 return new List<UserAccount>(); 326 return new List<UserAccount>();
diff --git a/OpenSim/Services/UserProfilesService/UserProfilesService.cs b/OpenSim/Services/UserProfilesService/UserProfilesService.cs
index 96c13c0..9a52e02 100644
--- a/OpenSim/Services/UserProfilesService/UserProfilesService.cs
+++ b/OpenSim/Services/UserProfilesService/UserProfilesService.cs
@@ -159,6 +159,7 @@ namespace OpenSim.Services.ProfilesService
159 } 159 }
160 #endregion Interests 160 #endregion Interests
161 161
162
162 #region User Preferences 163 #region User Preferences
163 public bool UserPreferencesUpdate(ref UserPreferences pref, ref string result) 164 public bool UserPreferencesUpdate(ref UserPreferences pref, ref string result)
164 { 165 {
@@ -239,6 +240,7 @@ namespace OpenSim.Services.ProfilesService
239 } 240 }
240 #endregion User Preferences 241 #endregion User Preferences
241 242
243
242 #region Utility 244 #region Utility
243 public OSD AvatarImageAssetsRequest(UUID avatarId) 245 public OSD AvatarImageAssetsRequest(UUID avatarId)
244 { 246 {
diff --git a/OpenSim/Tests/Clients/Grid/GridClient.cs b/OpenSim/Tests/Clients/Grid/GridClient.cs
new file mode 100644
index 0000000..fed7a16
--- /dev/null
+++ b/OpenSim/Tests/Clients/Grid/GridClient.cs
@@ -0,0 +1,205 @@
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;
31using System.Reflection;
32
33using OpenMetaverse;
34using log4net;
35using log4net.Appender;
36using log4net.Layout;
37
38using OpenSim.Framework;
39using OpenSim.Services.Interfaces;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41using OpenSim.Services.Connectors;
42
43namespace OpenSim.Tests.Clients.GridClient
44{
45 public class GridClient
46 {
47// private static readonly ILog m_log =
48// LogManager.GetLogger(
49// MethodBase.GetCurrentMethod().DeclaringType);
50
51 public static void Main(string[] args)
52 {
53 ConsoleAppender consoleAppender = new ConsoleAppender();
54 consoleAppender.Layout =
55 new PatternLayout("%date [%thread] %-5level %logger [%property{NDC}] - %message%newline");
56 log4net.Config.BasicConfigurator.Configure(consoleAppender);
57
58 string serverURI = "http://127.0.0.1:8001";
59 GridServicesConnector m_Connector = new GridServicesConnector(serverURI);
60
61 GridRegion r1 = CreateRegion("Test Region 1", 1000, 1000);
62 GridRegion r2 = CreateRegion("Test Region 2", 1001, 1000);
63 GridRegion r3 = CreateRegion("Test Region 3", 1005, 1000);
64
65 Console.WriteLine("[GRID CLIENT]: *** Registering region 1");
66 string msg = m_Connector.RegisterRegion(UUID.Zero, r1);
67 if (msg == String.Empty)
68 Console.WriteLine("[GRID CLIENT]: Successfully registered region 1");
69 else
70 Console.WriteLine("[GRID CLIENT]: region 1 failed to register");
71
72 Console.WriteLine("[GRID CLIENT]: *** Registering region 2");
73 msg = m_Connector.RegisterRegion(UUID.Zero, r2);
74 if (msg == String.Empty)
75 Console.WriteLine("[GRID CLIENT]: Successfully registered region 2");
76 else
77 Console.WriteLine("[GRID CLIENT]: region 2 failed to register");
78
79 Console.WriteLine("[GRID CLIENT]: *** Registering region 3");
80 msg = m_Connector.RegisterRegion(UUID.Zero, r3);
81 if (msg == String.Empty)
82 Console.WriteLine("[GRID CLIENT]: Successfully registered region 3");
83 else
84 Console.WriteLine("[GRID CLIENT]: region 3 failed to register");
85
86
87 bool success;
88 Console.WriteLine("[GRID CLIENT]: *** Deregistering region 3");
89 success = m_Connector.DeregisterRegion(r3.RegionID);
90 if (success)
91 Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 3");
92 else
93 Console.WriteLine("[GRID CLIENT]: region 3 failed to deregister");
94 Console.WriteLine("[GRID CLIENT]: *** Registering region 3 again");
95 msg = m_Connector.RegisterRegion(UUID.Zero, r3);
96 if (msg == String.Empty)
97 Console.WriteLine("[GRID CLIENT]: Successfully registered region 3");
98 else
99 Console.WriteLine("[GRID CLIENT]: region 3 failed to register");
100
101 Console.WriteLine("[GRID CLIENT]: *** GetNeighbours of region 1");
102 List<GridRegion> regions = m_Connector.GetNeighbours(UUID.Zero, r1.RegionID);
103 if (regions == null)
104 Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 failed");
105 else if (regions.Count > 0)
106 {
107 if (regions.Count != 1)
108 Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned more neighbours than expected: " + regions.Count);
109 else
110 Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned the right neighbour " + regions[0].RegionName);
111 }
112 else
113 Console.WriteLine("[GRID CLIENT]: GetNeighbours of region 1 returned 0 neighbours");
114
115
116 Console.WriteLine("[GRID CLIENT]: *** GetRegionByUUID of region 2 (this should succeed)");
117 GridRegion region = m_Connector.GetRegionByUUID(UUID.Zero, r2.RegionID);
118 if (region == null)
119 Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned null");
120 else
121 Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned region " + region.RegionName);
122
123 Console.WriteLine("[GRID CLIENT]: *** GetRegionByUUID of non-existent region (this should fail)");
124 region = m_Connector.GetRegionByUUID(UUID.Zero, UUID.Random());
125 if (region == null)
126 Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned null");
127 else
128 Console.WriteLine("[GRID CLIENT]: GetRegionByUUID returned region " + region.RegionName);
129
130 Console.WriteLine("[GRID CLIENT]: *** GetRegionByName of region 3 (this should succeed)");
131 region = m_Connector.GetRegionByName(UUID.Zero, r3.RegionName);
132 if (region == null)
133 Console.WriteLine("[GRID CLIENT]: GetRegionByName returned null");
134 else
135 Console.WriteLine("[GRID CLIENT]: GetRegionByName returned region " + region.RegionName);
136
137 Console.WriteLine("[GRID CLIENT]: *** GetRegionByName of non-existent region (this should fail)");
138 region = m_Connector.GetRegionByName(UUID.Zero, "Foo");
139 if (region == null)
140 Console.WriteLine("[GRID CLIENT]: GetRegionByName returned null");
141 else
142 Console.WriteLine("[GRID CLIENT]: GetRegionByName returned region " + region.RegionName);
143
144 Console.WriteLine("[GRID CLIENT]: *** GetRegionsByName (this should return 3 regions)");
145 regions = m_Connector.GetRegionsByName(UUID.Zero, "Test", 10);
146 if (regions == null)
147 Console.WriteLine("[GRID CLIENT]: GetRegionsByName returned null");
148 else
149 Console.WriteLine("[GRID CLIENT]: GetRegionsByName returned " + regions.Count + " regions");
150
151 Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 2 regions)");
152 regions = m_Connector.GetRegionRange(UUID.Zero,
153 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002),
154 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(1002) );
155 if (regions == null)
156 Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null");
157 else
158 Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions");
159 Console.WriteLine("[GRID CLIENT]: *** GetRegionRange (this should return 0 regions)");
160 regions = m_Connector.GetRegionRange(UUID.Zero,
161 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950),
162 (int)Util.RegionToWorldLoc(900), (int)Util.RegionToWorldLoc(950) );
163 if (regions == null)
164 Console.WriteLine("[GRID CLIENT]: GetRegionRange returned null");
165 else
166 Console.WriteLine("[GRID CLIENT]: GetRegionRange returned " + regions.Count + " regions");
167
168 Console.Write("Proceed to deregister? Press enter...");
169 Console.ReadLine();
170
171 // Deregister them all
172 Console.WriteLine("[GRID CLIENT]: *** Deregistering region 1");
173 success = m_Connector.DeregisterRegion(r1.RegionID);
174 if (success)
175 Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 1");
176 else
177 Console.WriteLine("[GRID CLIENT]: region 1 failed to deregister");
178 Console.WriteLine("[GRID CLIENT]: *** Deregistering region 2");
179 success = m_Connector.DeregisterRegion(r2.RegionID);
180 if (success)
181 Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 2");
182 else
183 Console.WriteLine("[GRID CLIENT]: region 2 failed to deregister");
184 Console.WriteLine("[GRID CLIENT]: *** Deregistering region 3");
185 success = m_Connector.DeregisterRegion(r3.RegionID);
186 if (success)
187 Console.WriteLine("[GRID CLIENT]: Successfully deregistered region 3");
188 else
189 Console.WriteLine("[GRID CLIENT]: region 3 failed to deregister");
190
191 }
192
193 private static GridRegion CreateRegion(string name, uint xcell, uint ycell)
194 {
195 GridRegion region = new GridRegion(xcell, ycell);
196 region.RegionName = name;
197 region.RegionID = UUID.Random();
198 region.ExternalHostName = "127.0.0.1";
199 region.HttpPort = 9000;
200 region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), 9000);
201
202 return region;
203 }
204 }
205}
diff --git a/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs b/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
index b215f1e..1f6233d 100644
--- a/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
@@ -120,4 +120,4 @@ namespace OpenSim.Tests.Common
120 }; 120 };
121 } 121 }
122 } 122 }
123} \ No newline at end of file 123}
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index df8b14c..9ab8d13 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -201,7 +201,7 @@ namespace OpenSim.Tests.Common
201 testScene.SetModuleInterfaces(); 201 testScene.SetModuleInterfaces();
202 202
203 testScene.LandChannel = new TestLandChannel(testScene); 203 testScene.LandChannel = new TestLandChannel(testScene);
204 testScene.LoadWorldMap(); 204 testScene.LoadWorldMap();
205 205
206 testScene.RegionInfo.EstateSettings = new EstateSettings(); 206 testScene.RegionInfo.EstateSettings = new EstateSettings();
207 testScene.LoginsEnabled = true; 207 testScene.LoginsEnabled = true;
diff --git a/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs
index dddf75d..aaf61e7 100644
--- a/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs
@@ -54,9 +54,10 @@ namespace OpenSim.Tests.Common
54 return assets.Find(x=>x.FullID == uuid); 54 return assets.Find(x=>x.FullID == uuid);
55 } 55 }
56 56
57 public void StoreAsset(AssetBase asset) 57 public bool StoreAsset(AssetBase asset)
58 { 58 {
59 assets.Add(asset); 59 assets.Add(asset);
60 return true;
60 } 61 }
61 62
62 public List<AssetMetadata> FetchAssetMetadataSet(int start, int count) { return new List<AssetMetadata>(count); } 63 public List<AssetMetadata> FetchAssetMetadataSet(int start, int count) { return new List<AssetMetadata>(count); }
diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
index 5df8e04..3ab9020 100644
--- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
@@ -138,6 +138,11 @@ namespace OpenSim.Data.Null
138 m_store.RemoveRegionEnvironmentSettings(regionUUID); 138 m_store.RemoveRegionEnvironmentSettings(regionUUID);
139 } 139 }
140 140
141 public UUID[] GetObjectIDs(UUID regionID)
142 {
143 return new UUID[0];
144 }
145
141 public void SaveExtra(UUID regionID, string name, string value) 146 public void SaveExtra(UUID regionID, string name, string value)
142 { 147 {
143 } 148 }
@@ -355,6 +360,11 @@ namespace OpenSim.Data.Null
355 { 360 {
356 } 361 }
357 362
363 public UUID[] GetObjectIDs(UUID regionID)
364 {
365 return new UUID[0];
366 }
367
358 public void SaveExtra(UUID regionID, string name, string value) 368 public void SaveExtra(UUID regionID, string name, string value)
359 { 369 {
360 } 370 }
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 0e1bc8f..ff7ba00 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Tests.Common
88 public event MoneyTransferRequest OnMoneyTransferRequest; 88 public event MoneyTransferRequest OnMoneyTransferRequest;
89 public event ParcelBuy OnParcelBuy; 89 public event ParcelBuy OnParcelBuy;
90 public event Action<IClientAPI> OnConnectionClosed; 90 public event Action<IClientAPI> OnConnectionClosed;
91 91 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
92 public event ImprovedInstantMessage OnInstantMessage; 92 public event ImprovedInstantMessage OnInstantMessage;
93 public event ChatMessage OnChatFromClient; 93 public event ChatMessage OnChatFromClient;
94 public event TextureRequest OnRequestTexture; 94 public event TextureRequest OnRequestTexture;
@@ -105,6 +105,7 @@ namespace OpenSim.Tests.Common
105 public event ObjectDrop OnObjectDrop; 105 public event ObjectDrop OnObjectDrop;
106 public event StartAnim OnStartAnim; 106 public event StartAnim OnStartAnim;
107 public event StopAnim OnStopAnim; 107 public event StopAnim OnStopAnim;
108 public event ChangeAnim OnChangeAnim;
108 public event LinkObjects OnLinkObjects; 109 public event LinkObjects OnLinkObjects;
109 public event DelinkObjects OnDelinkObjects; 110 public event DelinkObjects OnDelinkObjects;
110 public event RequestMapBlocks OnRequestMapBlocks; 111 public event RequestMapBlocks OnRequestMapBlocks;
@@ -153,6 +154,7 @@ namespace OpenSim.Tests.Common
153 public event GenericCall7 OnObjectMaterial; 154 public event GenericCall7 OnObjectMaterial;
154 public event UpdatePrimFlags OnUpdatePrimFlags; 155 public event UpdatePrimFlags OnUpdatePrimFlags;
155 public event UpdatePrimTexture OnUpdatePrimTexture; 156 public event UpdatePrimTexture OnUpdatePrimTexture;
157 public event ClientChangeObject onClientChangeObject;
156 public event UpdateVector OnUpdatePrimGroupPosition; 158 public event UpdateVector OnUpdatePrimGroupPosition;
157 public event UpdateVector OnUpdatePrimSinglePosition; 159 public event UpdateVector OnUpdatePrimSinglePosition;
158 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 160 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -295,7 +297,7 @@ namespace OpenSim.Tests.Common
295 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 297 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
296 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 298 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
297 public event ClassifiedDelete OnClassifiedDelete; 299 public event ClassifiedDelete OnClassifiedDelete;
298 public event ClassifiedDelete OnClassifiedGodDelete; 300 public event ClassifiedGodDelete OnClassifiedGodDelete;
299 301
300 public event EventNotificationAddRequest OnEventNotificationAddRequest; 302 public event EventNotificationAddRequest OnEventNotificationAddRequest;
301 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 303 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
@@ -334,11 +336,12 @@ namespace OpenSim.Tests.Common
334 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 336 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
335 public event SimWideDeletesDelegate OnSimWideDeletes; 337 public event SimWideDeletesDelegate OnSimWideDeletes;
336 public event SendPostcard OnSendPostcard; 338 public event SendPostcard OnSendPostcard;
339 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
337 public event MuteListEntryUpdate OnUpdateMuteListEntry; 340 public event MuteListEntryUpdate OnUpdateMuteListEntry;
338 public event MuteListEntryRemove OnRemoveMuteListEntry; 341 public event MuteListEntryRemove OnRemoveMuteListEntry;
339 public event GodlikeMessage onGodlikeMessage; 342 public event GodlikeMessage onGodlikeMessage;
340 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 343 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
341 344 public event GenericCall2 OnUpdateThrottles;
342#pragma warning restore 67 345#pragma warning restore 67
343 346
344 /// <value> 347 /// <value>
@@ -387,6 +390,8 @@ namespace OpenSim.Tests.Common
387 get { return FirstName + " " + LastName; } 390 get { return FirstName + " " + LastName; }
388 } 391 }
389 392
393 public int PingTimeMS { get { return 0; } }
394
390 public bool IsActive 395 public bool IsActive
391 { 396 {
392 get { return true; } 397 get { return true; }
@@ -448,6 +453,8 @@ namespace OpenSim.Tests.Common
448 get { return new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode); } 453 get { return new IPEndPoint(IPAddress.Loopback, (ushort)m_circuitCode); }
449 } 454 }
450 455
456 public List<uint> SelectedObjects {get; private set;}
457
451 /// <summary> 458 /// <summary>
452 /// Constructor 459 /// Constructor
453 /// </summary> 460 /// </summary>
@@ -570,10 +577,27 @@ namespace OpenSim.Tests.Common
570 ReceivedKills.AddRange(localID); 577 ReceivedKills.AddRange(localID);
571 } 578 }
572 579
580 public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
581 {
582 }
583
573 public virtual void SetChildAgentThrottle(byte[] throttle) 584 public virtual void SetChildAgentThrottle(byte[] throttle)
574 { 585 {
575 } 586 }
576 587
588 public virtual void SetChildAgentThrottle(byte[] throttle, float factor)
589 {
590 }
591
592 public void SetAgentThrottleSilent(int throttle, int setting)
593 {
594 }
595
596 public int GetAgentThrottleSilent(int throttle)
597 {
598 return 0;
599 }
600
577 public byte[] GetThrottlesPacked(float multiplier) 601 public byte[] GetThrottlesPacked(float multiplier)
578 { 602 {
579 return new byte[0]; 603 return new byte[0];
@@ -608,6 +632,11 @@ namespace OpenSim.Tests.Common
608 632
609 } 633 }
610 634
635 public virtual bool CanSendLayerData()
636 {
637 return false;
638 }
639
611 public virtual void SendLayerData(float[] map) 640 public virtual void SendLayerData(float[] map)
612 { 641 {
613 } 642 }
@@ -755,6 +784,10 @@ namespace OpenSim.Tests.Common
755 { 784 {
756 } 785 }
757 786
787 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
788 {
789 }
790
758 public virtual void SendRemoveInventoryItem(UUID itemID) 791 public virtual void SendRemoveInventoryItem(UUID itemID)
759 { 792 {
760 } 793 }
@@ -771,7 +804,7 @@ namespace OpenSim.Tests.Common
771 { 804 {
772 } 805 }
773 806
774 public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data) 807 public virtual void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
775 { 808 {
776 } 809 }
777 810
@@ -910,8 +943,13 @@ namespace OpenSim.Tests.Common
910 ReceivedOnlineNotifications.AddRange(agentIDs); 943 ReceivedOnlineNotifications.AddRange(agentIDs);
911 } 944 }
912 945
913 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, 946 public void SendFindAgent(UUID HunterID, UUID PreyID, double GlobalX, double GlobalY)
914 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) 947 {
948 }
949
950 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos,
951 Quaternion SitOrientation, bool autopilot,
952 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
915 { 953 {
916 } 954 }
917 955
@@ -966,10 +1004,10 @@ namespace OpenSim.Tests.Common
966 1004
967 public void Close() 1005 public void Close()
968 { 1006 {
969 Close(false); 1007 Close(true, false);
970 } 1008 }
971 1009
972 public void Close(bool force) 1010 public void Close(bool sendStop, bool force)
973 { 1011 {
974 // Fire the callback for this connection closing 1012 // Fire the callback for this connection closing
975 // This is necesary to get the presence detector to notice that a client has logged out. 1013 // This is necesary to get the presence detector to notice that a client has logged out.
@@ -1175,6 +1213,10 @@ namespace OpenSim.Tests.Common
1175 { 1213 {
1176 } 1214 }
1177 1215
1216 public void SendAgentGroupDataUpdate(UUID avatarID, GroupMembershipData[] data)
1217 {
1218 }
1219
1178 public void SendJoinGroupReply(UUID groupID, bool success) 1220 public void SendJoinGroupReply(UUID groupID, bool success)
1179 { 1221 {
1180 } 1222 }
@@ -1318,6 +1360,5 @@ namespace OpenSim.Tests.Common
1318 public void SendPartPhysicsProprieties(ISceneEntity entity) 1360 public void SendPartPhysicsProprieties(ISceneEntity entity)
1319 { 1361 {
1320 } 1362 }
1321
1322 } 1363 }
1323} 1364}
diff --git a/OpenSim/Tests/Common/Mock/TestLandChannel.cs b/OpenSim/Tests/Common/Mock/TestLandChannel.cs
index 89ebcd5..23258ad 100644
--- a/OpenSim/Tests/Common/Mock/TestLandChannel.cs
+++ b/OpenSim/Tests/Common/Mock/TestLandChannel.cs
@@ -111,5 +111,6 @@ namespace OpenSim.Tests.Common
111 111
112 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) {} 112 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) {}
113 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) {} 113 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) {}
114 public void sendClientInitialLandInfo(IClientAPI remoteClient) { }
114 } 115 }
115} \ No newline at end of file 116} \ No newline at end of file
diff --git a/OpenSim/Tests/Performance/NPCPerformanceTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
index ca6ae42..e41f5d1 100644
--- a/OpenSim/Tests/Performance/NPCPerformanceTests.cs
+++ b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
@@ -143,8 +143,7 @@ namespace OpenSim.Tests.Performance
143 // ScenePresence.SendInitialData() to reset our entire appearance. 143 // ScenePresence.SendInitialData() to reset our entire appearance.
144 scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); 144 scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId));
145 145
146/* 146 afm.SetAppearance(sp, originalTe, null, new WearableCacheItem[0]);
147 afm.SetAppearance(sp, originalTe, null);
148 147
149 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>(); 148 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
150 149
@@ -185,7 +184,6 @@ namespace OpenSim.Tests.Performance
185 endGcMemory / 1024 / 1024, 184 endGcMemory / 1024 / 1024,
186 startGcMemory / 1024 / 1024, 185 startGcMemory / 1024 / 1024,
187 (endGcMemory - startGcMemory) / 1024 / 1024); 186 (endGcMemory - startGcMemory) / 1024 / 1024);
188*/
189 } 187 }
190 } 188 }
191} 189}
diff --git a/bin/MsgPack.dll b/bin/MsgPack.dll
new file mode 100755
index 0000000..90e6b7b
--- /dev/null
+++ b/bin/MsgPack.dll
Binary files differ
diff --git a/bin/OpenSim.Region.PhysicsModule.ubOde.dll.config b/bin/OpenSim.Region.PhysicsModule.ubOde.dll.config
new file mode 100644
index 0000000..c72c281
--- /dev/null
+++ b/bin/OpenSim.Region.PhysicsModule.ubOde.dll.config
@@ -0,0 +1,7 @@
1<configuration>
2 <dllmap os="osx" dll="ode" target="lib64/libode.dylib" />
3 <dllmap os="!windows,osx" cpu="x86-64,ia64" dll="ode" target="lib64/libode-x86_64" />
4 <dllmap os="!windows,osx" cpu="x86" dll="ode" target="lib32/libode" />
5 <dllmap os="!windows,osx" cpu="ppc64" dll="ode" target="lib64/libode-ppc64" />
6 <dllmap os="!windows,osx" cpu="s390x" dll="ode" target="lib64/libode-s390x" />
7</configuration>
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index d395efe..e4adb7f 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -142,10 +142,6 @@
142 ;; from the selected region_info_source. 142 ;; from the selected region_info_source.
143 ; allow_regionless = false 143 ; allow_regionless = false
144 144
145 ;# {MaxPrimUndos} {} {Maximum number of undos avialable for position, rotation and scale changes of each prim} {} 20
146 ;; Increasing the number of undos available number will increase memory usage.
147 MaxPrimUndos = 20
148
149 ;# {NonPhysicalPrimMin} {} {Minimum size of nonphysical prims?} {} 0.001 145 ;# {NonPhysicalPrimMin} {} {Minimum size of nonphysical prims?} {} 0.001
150 ;; Minimum size for non-physical prims. Affects resizing of existing 146 ;; Minimum size for non-physical prims. Affects resizing of existing
151 ;; prims. This can be overridden in the region config file (as 147 ;; prims. This can be overridden in the region config file (as
@@ -248,7 +244,9 @@
248 ;; Default is Meshmerizer 244 ;; Default is Meshmerizer
249 ; meshing = Meshmerizer 245 ; meshing = Meshmerizer
250 ; meshing = ZeroMesher 246 ; meshing = ZeroMesher
251 247 ;; select ubODEMeshmerizer only with ubOde physics engine
248 ; meshing = ubODEMeshmerizer
249
252 ;; Choose one of the physics engines below 250 ;; Choose one of the physics engines below
253 ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} BulletSim 251 ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} BulletSim
254 ;; BulletSim is the default physics engine. It provides the best performance and most functionality. 252 ;; BulletSim is the default physics engine. It provides the best performance and most functionality.
@@ -261,6 +259,8 @@
261 ; physics = BulletSim 259 ; physics = BulletSim
262 ; physics = basicphysics 260 ; physics = basicphysics
263 ; physics = POS 261 ; physics = POS
262 ;; alternative OpenDynamicsEngine engine. ubODEMeshmerizer meshing above MUST be selected also
263 ; physics = ubODE
264 264
265 ;# {DefaultScriptEngine} {} {Default script engine} {XEngine} XEngine 265 ;# {DefaultScriptEngine} {} {Default script engine} {XEngine} XEngine
266 ;; Default script engine to use. Currently, we only have XEngine 266 ;; Default script engine to use. Currently, we only have XEngine
@@ -695,7 +695,6 @@
695 ;; (see NINJA Physics, http://opensimulator.org/wiki/NINJA_Physics) 695 ;; (see NINJA Physics, http://opensimulator.org/wiki/NINJA_Physics)
696 ; use_NINJA_physics_joints = false 696 ; use_NINJA_physics_joints = false
697 697
698
699[RemoteAdmin] 698[RemoteAdmin]
700 ;; This is the remote admin module, which uses XMLRPC requests to 699 ;; This is the remote admin module, which uses XMLRPC requests to
701 ;; manage regions from a web interface. 700 ;; manage regions from a web interface.
@@ -1114,6 +1113,20 @@
1114[NPC] 1113[NPC]
1115 ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} false 1114 ;# {Enabled} {} {Enable Non Player Character (NPC) facilities} {true false} false
1116 ; Enabled = false 1115 ; Enabled = false
1116
1117 ;; several options to control NPCs creation
1118
1119 ;; allow NPCs to be created not Owned {true false} default: true
1120 ; AllowNotOwned = false
1121
1122 ;; allow NPCs to set to be sensed as Avatars {true false} default: true
1123 ; AllowSenseAsAvatar = false
1124
1125 ;; allow NPCs to created cloning any avatar in region {true false} default: true
1126 ; AllowCloneOtherAvatars = false
1127
1128 ;; if true NPCs will have no group title, if false display "- NPC -" for easy identification {true false} default: true
1129 ; NoNPCGroup = false
1117 1130
1118 1131
1119[Terrain] 1132[Terrain]
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index a99608c..f1d6f84 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -176,11 +176,14 @@
176 ; You can choose to show the true physics FPS to viewers by setting Normalized55FPS to false. 176 ; You can choose to show the true physics FPS to viewers by setting Normalized55FPS to false.
177 ; Normalized55FPS = true 177 ; Normalized55FPS = true
178 178
179 ; The minimum proportion of a second that any particular frame can take to execute. 179 ; Main Frame time
180 ; Only change this if you really know what you're doing, and be prepared to change UpdatePhysicsEveryNFrames 180 ; This defines the rate of several simulation events.
181 ; (and other Frames params) to match! For instance, halving MinFrameTime to 0.0445 require 181 ; Default value should meet most needs.
182 ; UpdatePhysicsEveryNFrames = 2 unless you don't mind your avatar walking like Benny Hill. 182 ; It can be reduced to improve the simulation of moving objects, with possible increase of cpu and network loads.
183 MinFrameTime = 0.089 183 ; It should not be less than the physics engine step time.
184 ; Being a integer multiple of it may reduce some jitter in reported physics FPS.
185 ; changing this value, you need to change some of the following *EveryNFrames so their actions timing remains the same
186 FrameTime = 0.0909
184 187
185 ; The values below represent the percentage of the target frame time that, 188 ; The values below represent the percentage of the target frame time that,
186 ; when underrun, should trigger yellow or red in the lag meter. 189 ; when underrun, should trigger yellow or red in the lag meter.
@@ -189,24 +192,24 @@
189 ; encouraged that they do. 192 ; encouraged that they do.
190 ; FrameTimeWarnPercent = 60; 193 ; FrameTimeWarnPercent = 60;
191 ; FrameTimeCritPercent = 40; 194 ; FrameTimeCritPercent = 40;
192 195
193 ; Send scheduled updates to objects in the scene 196 ; Send scheduled updates to objects in the scene
194 ; This must be a whole number 197 ; This must be a whole number
195 UpdateObjectsEveryNFrames = 1; 198 UpdateObjectsEveryNFrames = 1;
196 199
197 ; Send position/velocity, etc. updates to agents in the scene 200 ; Send position/velocity, etc. updates to agents in the scene
198 ; This must be a whole number 201 ; This must be a whole number
199 UpdateAgentsEveryNFrames = 1; 202 UpdateAgentsEveryNFrames = 1;
200 203
201 ; Apply pending forces from physics calculations to an entity. 204 ; Apply pending forces from physics calculations to an entity.
202 ; This must be a whole number 205 ; This must be a whole number
203 UpdateEntityMovementEveryNFrames = 1; 206 UpdateEntityMovementEveryNFrames = 1;
204 207
205 ; Send coarse location updates to viewers. In a classic viewer, this updates the minimap. 208 ; Send coarse location updates to viewers. In a classic viewer, this updates the minimap.
206 ; This must be a whole number 209 ; This must be a whole number
207 UpdateCoarseLocationsEveryNFrames = 50; 210 UpdateCoarseLocationsEveryNFrames = 50;
208 211
209 ; Update physics. Within each update physics also updates in a series of contigous mini-steps 212 ; Physics simulation execution or syncronization, acording to engine. Should be 1
210 ; This must be a whole number 213 ; This must be a whole number
211 UpdatePhysicsEveryNFrames = 1; 214 UpdatePhysicsEveryNFrames = 1;
212 215
@@ -609,7 +612,7 @@
609 ; clients login by starting each connection more slowly. Disabled by 612 ; clients login by starting each connection more slowly. Disabled by
610 ; default 613 ; default
611 ; 614 ;
612 enable_adaptive_throttles = true 615 enable_adaptive_throttles = false
613 616
614 ; Per-client bytes per second rates for the various throttle categories. 617 ; Per-client bytes per second rates for the various throttle categories.
615 ; These are default values that will be overridden by clients. These 618 ; These are default values that will be overridden by clients. These
@@ -908,19 +911,24 @@
908 ; Max value is 255, min value is 0 911 ; Max value is 255, min value is 0
909 avatar_terminal_velocity = 54 912 avatar_terminal_velocity = 54
910 913
911 ; World Step size. (warning these are dangerous. Changing these will probably cause your scene to explode dramatically) 914 ; World Step size.
912 ; reference: fps = (0.089/ODE_STEPSIZE) * 1000; 915 ; with legacy ODE this value needs to be close to 0.02s
913 world_stepsize = 0.0178 916 ; with ubOde this value can be reduced to improve simulation quality with the cost of higher cpu load
914 world_internal_steps_without_collisions = 10 917 ; you will need to test acording to you needs
918 ; choosing a value that is a integer sub multiple of FrameRate reduces some jitter on reported physics FPS
919 world_stepsize = 0.01818
920 ; number of iterations of constrains solver, higher should improve results
921 ; up to a point where acumulated math errors eliminate the improvement
922 ; more steps may increase CPU load. No real gain in changing
923 world_solver_iterations = 10
924
925 ;Spaces level settings. Affects memory consumption vs Collider CPU time for avatar and physical prim
926 ; defines spaces partition cells min and max sizes == 2^value
927 world_hashspace_level_low = -5
928 world_hashSpace_level_high = 12
915 929
916 ;World Space settings. Affects memory consumption vs Collider CPU time for avatar and physical prim
917 world_hashspace_size_low = -4
918 world_hashSpace_size_high = 128
919
920 ;Dynamic space settings Affects memory consumption vs Collider CPU time for static prim
921 meters_in_small_space = 29.9 930 meters_in_small_space = 29.9
922 small_hashspace_size_low = -4 931
923 small_hashspace_size_high = 66
924 932
925 ; ## 933 ; ##
926 ; ## Contact properties. (the stuff that happens when things come in contact with each other) 934 ; ## Contact properties. (the stuff that happens when things come in contact with each other)
@@ -959,18 +967,14 @@
959 ; desired velocity 967 ; desired velocity
960 ; See http://en.wikipedia.org/wiki/PID_controller 968 ; See http://en.wikipedia.org/wiki/PID_controller
961 969
962 av_pid_derivative_linux = 2200.0 970 av_pid_derivative = 2200.0
963 av_pid_proportional_linux = 900.0; 971 av_pid_proportional = 900.0;
964
965 av_pid_derivative_win = 2200.0
966 av_pid_proportional_win = 900.0;
967 972
968 ;girth of the avatar. Adds radius to the height also 973 ;girth of the avatar. Adds radius to the height also
969 av_capsule_radius = 0.37 974 av_capsule_radius = 0.37
970 975
971 ; Max force permissible to use to keep the avatar standing up straight 976 ; Max force permissible to use to keep the avatar standing up straight
972 av_capsule_standup_tensor_win = 550000 977 av_capsule_standup_tensor = 550000
973 av_capsule_standup_tensor_linux = 550000
974 978
975 ; specifies if the capsule should be tilted (=true; old compatibility mode) 979 ; specifies if the capsule should be tilted (=true; old compatibility mode)
976 ; or straight up-and-down (=false; better and more consistent physics behavior) 980 ; or straight up-and-down (=false; better and more consistent physics behavior)
@@ -1022,19 +1026,12 @@
1022 ; maximum number of contact points to generate per collision 1026 ; maximum number of contact points to generate per collision
1023 contacts_per_collision = 80 1027 contacts_per_collision = 80
1024 1028
1025 ; amount of time a geom/body will try to cross a region border before it gets disabled
1026 geom_crossing_failures_before_outofbounds = 5
1027
1028 ; start throttling the object updates if object comes in contact with 3 or more other objects 1029 ; start throttling the object updates if object comes in contact with 3 or more other objects
1029 geom_contactpoints_start_throttling = 3 1030 geom_contactpoints_start_throttling = 3
1030 1031
1031 ; send 1 update for every x updates below when throttled 1032 ; send 1 update for every x updates below when throttled
1032 geom_updates_before_throttled_update = 15 1033 geom_updates_before_throttled_update = 15
1033 1034
1034 ; Used for llSetStatus. How rigid the object rotation is held on the axis specified
1035 body_motor_joint_maxforce_tensor_linux = 5
1036 body_motor_joint_maxforce_tensor_win = 5
1037
1038 ; Maximum mass an object can be before it is clamped 1035 ; Maximum mass an object can be before it is clamped
1039 maximum_mass_object = 10000.01 1036 maximum_mass_object = 10000.01
1040 1037
@@ -1940,7 +1937,7 @@
1940 GroupsCacheTimeout = 30 1937 GroupsCacheTimeout = 30
1941 1938
1942 ; Specify which messaging module to use for groups messaging and if it's enabled 1939 ; Specify which messaging module to use for groups messaging and if it's enabled
1943 MessagingModule = GroupsMessagingModule 1940 ;MessagingModule = GroupsMessagingModule
1944 ;MessagingEnabled = true 1941 ;MessagingEnabled = true
1945 1942
1946 ; Experimental option to only message cached online users rather than all users 1943 ; Experimental option to only message cached online users rather than all users
diff --git a/bin/assets/TexturesAssetSet/defaultalpha.jp2 b/bin/assets/TexturesAssetSet/defaultalpha.jp2
new file mode 100644
index 0000000..af73c1e
--- /dev/null
+++ b/bin/assets/TexturesAssetSet/defaultalpha.jp2
Binary files differ
diff --git a/bin/enter_uuid.xml b/bin/enter_uuid.xml
new file mode 100644
index 0000000..84475ad
--- /dev/null
+++ b/bin/enter_uuid.xml
@@ -0,0 +1,7 @@
1<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
2<floater can_close="true" can_drag_on_left="false" can_minimize="false" can_resize="false" height="100" name="enter_uuid" title="ID Required" width="390">
3 <text bottom="-30" left="10">Enter UUID</text>
4 <line_editor bottom="-60" left="10" width="370" name="new_owner" height="20"/>
5 <button bottom="-90" width="80" height="20" left="300" label="OK" name="ok" />
6 <button bottom="-90" width="80" height="20" left="210" label="Cancel" name="cancel" />
7</floater>
diff --git a/bin/lib32/libode.so b/bin/lib32/libode.so
index 6bb85fb..5b110ae 100644..100755
--- a/bin/lib32/libode.so
+++ b/bin/lib32/libode.so
Binary files differ
diff --git a/bin/lib32/ode.dll b/bin/lib32/ode.dll
index f310358..8457e50 100755
--- a/bin/lib32/ode.dll
+++ b/bin/lib32/ode.dll
Binary files differ
diff --git a/bin/lib64/ode.dll b/bin/lib64/ode.dll
index df3a6c4..f47ae31 100755
--- a/bin/lib64/ode.dll
+++ b/bin/lib64/ode.dll
Binary files differ
diff --git a/bin/set_object_owner.xml b/bin/set_object_owner.xml
new file mode 100644
index 0000000..6d9bb8a
--- /dev/null
+++ b/bin/set_object_owner.xml
@@ -0,0 +1,8 @@
1<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
2<floater can_close="true" can_drag_on_left="false" can_minimize="false" can_resize="false" height="100" name="set_owner_name" title="Set Owner Name" width="390">
3 <text bottom="-30" left="10">New Owner Name</text>
4 <line_editor enabled="false" bottom="-60" left="10" width="280" name="new_owner" height="20"/>
5 <button bottom_delta="0" left="300" height="20" width="80" label="Choose" name="picker"/>
6 <button bottom="-90" width="80" height="20" left="300" label="OK" name="ok" />
7 <button bottom="-90" width="80" height="20" left="210" label="Cancel" name="cancel" />
8</floater>
diff --git a/prebuild.xml b/prebuild.xml
index 4106d4d..06531cf 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -6,7 +6,7 @@
6 <CompilerDefines>TRACE;DEBUG</CompilerDefines> 6 <CompilerDefines>TRACE;DEBUG</CompilerDefines>
7 <OptimizeCode>false</OptimizeCode> 7 <OptimizeCode>false</OptimizeCode>
8 <CheckUnderflowOverflow>false</CheckUnderflowOverflow> 8 <CheckUnderflowOverflow>false</CheckUnderflowOverflow>
9 <AllowUnsafe>false</AllowUnsafe> 9 <AllowUnsafe>true</AllowUnsafe>
10 <WarningLevel>4</WarningLevel> 10 <WarningLevel>4</WarningLevel>
11 <WarningsAsErrors>false</WarningsAsErrors> 11 <WarningsAsErrors>false</WarningsAsErrors>
12 <SuppressWarnings/> 12 <SuppressWarnings/>
@@ -21,7 +21,7 @@
21 <CompilerDefines>TRACE</CompilerDefines> 21 <CompilerDefines>TRACE</CompilerDefines>
22 <OptimizeCode>true</OptimizeCode> 22 <OptimizeCode>true</OptimizeCode>
23 <CheckUnderflowOverflow>false</CheckUnderflowOverflow> 23 <CheckUnderflowOverflow>false</CheckUnderflowOverflow>
24 <AllowUnsafe>false</AllowUnsafe> 24 <AllowUnsafe>true</AllowUnsafe>
25 <WarningLevel>4</WarningLevel> 25 <WarningLevel>4</WarningLevel>
26 <WarningsAsErrors>false</WarningsAsErrors> 26 <WarningsAsErrors>false</WarningsAsErrors>
27 <SuppressWarnings/> 27 <SuppressWarnings/>
@@ -820,6 +820,7 @@
820 <Reference name="OpenSim.Server.Base"/> 820 <Reference name="OpenSim.Server.Base"/>
821 <Reference name="OpenSim.Services.Interfaces"/> 821 <Reference name="OpenSim.Services.Interfaces"/>
822 <Reference name="OpenSim.Services.Base"/> 822 <Reference name="OpenSim.Services.Base"/>
823 <Reference name="OpenSim.Server.Base"/>
823 <Reference name="OpenSim.Services.Connectors"/> 824 <Reference name="OpenSim.Services.Connectors"/>
824 <Reference name="OpenSim.Data"/> 825 <Reference name="OpenSim.Data"/>
825 <Reference name="Nini" path="../../../bin/"/> 826 <Reference name="Nini" path="../../../bin/"/>
@@ -1341,9 +1342,10 @@
1341 <Reference name="System.Drawing"/> 1342 <Reference name="System.Drawing"/>
1342 <Reference name="System.Xml"/> 1343 <Reference name="System.Xml"/>
1343 <Reference name="System.Web"/> 1344 <Reference name="System.Web"/>
1345 <Reference name="OpenMetaverse" path="../../../../../bin/"/>
1344 <Reference name="OpenMetaverseTypes" path="../../../../../bin/"/> 1346 <Reference name="OpenMetaverseTypes" path="../../../../../bin/"/>
1345 <Reference name="OpenMetaverse.StructuredData" path="../../../../../bin/"/> 1347 <Reference name="OpenMetaverse.StructuredData" path="../../../../../bin/"/>
1346 <Reference name="OpenMetaverse" path="../../../../../bin/"/> 1348
1347 <Reference name="OpenSim.Region.Framework"/> 1349 <Reference name="OpenSim.Region.Framework"/>
1348 <Reference name="OpenSim.Capabilities"/> 1350 <Reference name="OpenSim.Capabilities"/>
1349 <Reference name="OpenSim.Capabilities.Handlers"/> 1351 <Reference name="OpenSim.Capabilities.Handlers"/>
@@ -1358,6 +1360,7 @@
1358 <Reference name="Nini" path="../../../../../bin/"/> 1360 <Reference name="Nini" path="../../../../../bin/"/>
1359 <Reference name="log4net" path="../../../../../bin/"/> 1361 <Reference name="log4net" path="../../../../../bin/"/>
1360 <Reference name="Nini" path="../../../../../bin/"/> 1362 <Reference name="Nini" path="../../../../../bin/"/>
1363 <Reference name="zlib.net" path="../../../../../bin/"/>
1361 1364
1362 <Files> 1365 <Files>
1363 <Match pattern="*.cs" recurse="true"> 1366 <Match pattern="*.cs" recurse="true">
@@ -1423,6 +1426,7 @@
1423 1426
1424 <!-- To allow regions to have mono addins --> 1427 <!-- To allow regions to have mono addins -->
1425 <Reference name="Mono.Addins" path="../../../bin/"/> 1428 <Reference name="Mono.Addins" path="../../../bin/"/>
1429 <Reference name="SmartThreadPool"/>
1426 1430
1427 <Files> 1431 <Files>
1428 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/> 1432 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
@@ -1467,6 +1471,8 @@
1467 <Reference name="OpenSim.Framework.Servers.HttpServer"/> 1471 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
1468 <Reference name="OpenSim.Region.CoreModules"/> 1472 <Reference name="OpenSim.Region.CoreModules"/>
1469 <Reference name="OpenSim.Region.ClientStack.LindenUDP"/> 1473 <Reference name="OpenSim.Region.ClientStack.LindenUDP"/>
1474 <Reference name="OpenSim.Region.Framework.Interfaces"/>
1475 <Reference name="OpenSim.Region.Framework.Scenes"/>
1470 <Reference name="OpenSim.Region.Framework"/> 1476 <Reference name="OpenSim.Region.Framework"/>
1471 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/> 1477 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/>
1472 <Reference name="OpenSim.Server.Base"/> 1478 <Reference name="OpenSim.Server.Base"/>
@@ -1519,7 +1525,7 @@
1519 </Files> 1525 </Files>
1520 </Project> 1526 </Project>
1521 1527
1522 <Project frameworkVersion="v4_0" name="OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet" path="OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet" type="Library"> 1528 <Project frameworkVersion="v4_0" name="OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet" path="OpenSim/Region/PhysicsModules/ConvexDecompositionDotNet" type="Library">
1523 <Configuration name="Debug"> 1529 <Configuration name="Debug">
1524 <Options> 1530 <Options>
1525 <OutputPath>../../../../bin/</OutputPath> 1531 <OutputPath>../../../../bin/</OutputPath>
@@ -1536,7 +1542,9 @@
1536 <Reference name="System.Core"/> 1542 <Reference name="System.Core"/>
1537 <Reference name="System.Data"/> 1543 <Reference name="System.Data"/>
1538 <Reference name="System.Xml"/> 1544 <Reference name="System.Xml"/>
1539 1545 <Reference name="OpenSim.Framework"/>
1546 <Reference name="Mono.Addins" path="../../../../bin/"/>
1547
1540 <Files> 1548 <Files>
1541 <Match pattern="*.cs" recurse="true"> 1549 <Match pattern="*.cs" recurse="true">
1542 <Exclude name="Tests" pattern="Tests"/> 1550 <Exclude name="Tests" pattern="Tests"/>
@@ -1544,7 +1552,7 @@
1544 </Files> 1552 </Files>
1545 </Project> 1553 </Project>
1546 1554
1547 <Project frameworkVersion="v4_0" name="OpenSim.Region.PhysicsModules.Meshing" path="OpenSim/Region/PhysicsModules/Meshing" type="Library"> 1555 <Project frameworkVersion="v4_0" name="OpenSim.Region.PhysicsModule.Meshing" path="OpenSim/Region/PhysicsModules/Meshing" type="Library">
1548 <Configuration name="Debug"> 1556 <Configuration name="Debug">
1549 <Options> 1557 <Options>
1550 <OutputPath>../../../../bin/</OutputPath> 1558 <OutputPath>../../../../bin/</OutputPath>
@@ -1659,6 +1667,72 @@
1659 </Files> 1667 </Files>
1660 </Project> 1668 </Project>
1661 1669
1670 <Project frameworkVersion="v4_0" name="OpenSim.Region.PhysicsModule.ubOde" path="OpenSim/Region/PhysicsModules/ubOde" type="Library">
1671 <Configuration name="Debug">
1672 <Options>
1673 <OutputPath>../../../../bin/</OutputPath>
1674 </Options>
1675 </Configuration>
1676 <Configuration name="Release">
1677 <Options>
1678 <OutputPath>../../../../bin/</OutputPath>
1679 </Options>
1680 </Configuration>
1681
1682 <ReferencePath>../../../../bin/</ReferencePath>
1683 <Reference name="System"/>
1684 <Reference name="System.Core"/>
1685 <Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
1686 <Reference name="Nini" path="../../../../bin/"/>
1687
1688 <Reference name="OpenSim.Framework"/>
1689 <Reference name="OpenSim.Framework.Console"/>
1690 <Reference name="OpenSim.Region.Framework"/>
1691 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/>
1692 <Reference name="OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet"/>
1693 <Reference name="Mono.Addins" path="../../../../bin/"/>
1694 <Reference name="log4net" path="../../../../bin/"/>
1695
1696 <Files>
1697 <Match pattern="*.cs" recurse="true">
1698 <Exclude name="Tests" pattern="Tests"/>
1699 </Match>
1700 </Files>
1701 </Project>
1702
1703 <Project frameworkVersion="v4_0" name="OpenSim.Region.PhysicsModule.ubOdeMeshing" path="OpenSim/Region/PhysicsModules/ubOdeMeshing" type="Library">
1704 <Configuration name="Debug">
1705 <Options>
1706 <OutputPath>../../../../bin/</OutputPath>
1707 </Options>
1708 </Configuration>
1709 <Configuration name="Release">
1710 <Options>
1711 <OutputPath>../../../../bin/</OutputPath>
1712 </Options>
1713 </Configuration>
1714
1715 <ReferencePath>../../../../bin/</ReferencePath>
1716 <Reference name="System"/>
1717 <Reference name="System.Drawing"/>
1718 <Reference name="CSJ2K" path="../../../../bin/"/>
1719 <Reference name="OpenMetaverseTypes" path="../../../../bin/"/>
1720 <Reference name="OpenMetaverse" path="../../../../bin/"/>
1721 <Reference name="OpenMetaverse.StructuredData" path="../../../../bin/"/>
1722 <Reference name="Nini" path="../../../../bin/"/>
1723 <Reference name="OpenSim.Framework"/>
1724 <Reference name="OpenSim.Framework.Console"/>
1725 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/>
1726 <Reference name="OpenSim.Region.Framework"/>
1727 <Reference name="OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet"/>
1728 <Reference name="Mono.Addins" path="../../../../bin/"/>
1729 <Reference name="log4net" path="../../../../bin/"/>
1730
1731 <Files>
1732 <Match pattern="*.cs" recurse="true"/>
1733 </Files>
1734 </Project>
1735
1662 <Project frameworkVersion="v4_0" name="OpenSim.Region.PhysicsModule.BulletS" path="OpenSim/Region/PhysicsModules/BulletS" type="Library"> 1736 <Project frameworkVersion="v4_0" name="OpenSim.Region.PhysicsModule.BulletS" path="OpenSim/Region/PhysicsModules/BulletS" type="Library">
1663 <Configuration name="Debug"> 1737 <Configuration name="Debug">
1664 <Options> 1738 <Options>
@@ -1684,8 +1758,8 @@
1684 <Reference name="OpenSim.Region.Framework"/> 1758 <Reference name="OpenSim.Region.Framework"/>
1685 <Reference name="OpenSim.Framework.Console"/> 1759 <Reference name="OpenSim.Framework.Console"/>
1686 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/> 1760 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/>
1687 <Reference name="OpenSim.Region.PhysicsModules.Meshing" path="../../../../bin/"/> 1761 <Reference name="OpenSim.Region.PhysicsModule.Meshing" path="../../../../bin/"/>
1688 <Reference name="OpenSim.Region.PhysicsModule.ConvexDecompositionDotNet"/> 1762 <Reference name="OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet"/>
1689 <Reference name="Mono.Addins" path="../../../../bin/"/> 1763 <Reference name="Mono.Addins" path="../../../../bin/"/>
1690 <Reference name="BulletXNA.dll" path="../../../../bin/"/> 1764 <Reference name="BulletXNA.dll" path="../../../../bin/"/>
1691 <Reference name="log4net.dll" path="../../../../bin/"/> 1765 <Reference name="log4net.dll" path="../../../../bin/"/>
@@ -2864,6 +2938,7 @@
2864 <Reference name="OpenSim.Framework.Servers.HttpServer"/> 2938 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
2865 <Reference name="OpenSim.Region.ClientStack.LindenCaps"/> 2939 <Reference name="OpenSim.Region.ClientStack.LindenCaps"/>
2866 <Reference name="OpenSim.Region.Framework"/> 2940 <Reference name="OpenSim.Region.Framework"/>
2941 <Reference name="OpenSim.Region.Framework.Interfaces"/>
2867 <Reference name="OpenSim.Region.CoreModules"/> 2942 <Reference name="OpenSim.Region.CoreModules"/>
2868 <Reference name="OpenSim.Region.OptionalModules"/> 2943 <Reference name="OpenSim.Region.OptionalModules"/>
2869 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/> 2944 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/>
@@ -3147,7 +3222,7 @@
3147 <Reference name="OpenSim.Framework"/> 3222 <Reference name="OpenSim.Framework"/>
3148 <Reference name="OpenSim.Tests.Common"/> 3223 <Reference name="OpenSim.Tests.Common"/>
3149 <Reference name="OpenSim.Region.Framework"/> 3224 <Reference name="OpenSim.Region.Framework"/>
3150 <Reference name="OpenSim.Region.PhysicsModules.Meshing"/> 3225 <Reference name="OpenSim.Region.PhysicsModule.Meshing"/>
3151 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/> 3226 <Reference name="OpenSim.Region.PhysicsModules.SharedBase"/>
3152 <Reference name="OpenSim.Region.PhysicsModule.BulletS"/> 3227 <Reference name="OpenSim.Region.PhysicsModule.BulletS"/>
3153 3228